C # 'da bir nesnenin boş olup olmadığını kontrol etme


226

Boşsa, bir nesne üzerinde daha fazla işlem yapılmasını önlemek istiyorum.

Aşağıdaki kodda nesnenin ikisinden biri tarafından boş olup olmadığını kontrol ediyorum:

if (!data.Equals(null))

ve

if (data != null)

Ancak, bir NullReferenceExceptionat alırım dataList.Add(data). Nesne null olsaydı, asla if-statement!

Bu nedenle, bunun bir nesnenin boş olup olmadığını kontrol etmenin uygun bir yolu olup olmadığını soruyorum:

public List<Object> dataList;
public  bool AddData(ref Object data)
    bool success = false;
    try
    {
        // I've also used "if (data != null)" which hasn't worked either
        if (!data.Equals(null))
        {
           //NullReferenceException occurs here ...
           dataList.Add(data);
           success = doOtherStuff(data);
        }
    }
    catch (Exception e)
    {
        throw new Exception(e.ToString());
    }
    return success;
}

Nesnenin null olup olmadığını kontrol etmenin doğru yolu buysa, ne yapıyorum (NullReferenceException özelliğini önlemek için nesne üzerinde daha fazla işlem yapılmasını nasıl önleyebilirim)?


13
Ayrıca kullanmalıdır throw e;karşıthrow new Exception(e.ToString());
Nix

17
C # 'da her zaman != nullnull çeklerinizde kullanmalısınız . .Equalsnesne null olduğunda her zaman bir istisna atar.
Kyle Trauberman

42
@Nix: throw e;Çok daha iyi değil. throw;, diğer taraftan ...
Jon

4
@developer: e.ToString()yalnızca hata iletisini değil, aynı zamanda tümünü InnerExceptionsve yığın izlemesini de içeren bir dize oluşturur . Yani bu çok ağır bir istisna mesajı. (Haklı olarak!) Bu bilgileri korumak ve ait olduğu yerde tutmak istiyorsanız, sadece kullanın throw;.
Jon

15
Try / catch şu anda hiçbir şey yapmıyor. Herkes sadece "atmak" kullanmak diyor ama istisna dışında bir şey yapmıyorsanız ama tekrar atmak, neden bir denemek / yakalamak bloğu var? Genellikle, istisnaları yeniden atmadan önce bunları nazikçe işlemek, kaynakları temizlemek ("son olarak" yan tümcesi ile daha iyi) veya bir tür günlük kaydı yapmak için istisnalar yakalarsınız. Bunların hiçbiri bu kodda olmuyor, bu yüzden denemeye / yakalamaya gerek yok.
David Peterson

Yanıtlar:


252

O değil dataolduğunu null, ancak dataList.

İle bir tane oluşturmanız gerekir

public List<Object> dataList = new List<Object>();

Daha da iyisi: bir alan olduğu için yap private. Ve sizi engelleyen bir şey yoksa, bunu da yapın readonly. Sadece iyi uygulama.

bir kenara

Geçersizliği kontrol etmenin doğru yolu if(data != null). Bu tür bir kontrol referans tipleri için her yerde mevcuttur; Hatta Nullable<T>ifade daha uygun bir yol olarak eşitlik operatörü geçersiz kılan nullable.HasValuebutlan kontrol ederken.

Bunu yaparsanız if(!data.Equals(null))o zaman bir alacak NullReferenceExceptioneğer data == null. Bu istisnadan kaçınmak ilk başta hedef olduğu için biraz komik.

Bunu da yapıyorsunuz:

catch (Exception e)
{
    throw new Exception(e.ToString());
}

Bu kesinlikle iyi değil. Oraya koyduğunuzu hayal edebiliyorum, böylece hala metodun içindeyken hata ayıklayıcıya girebilirsiniz, bu durumda bu paragrafı görmezden gelin. Aksi takdirde, hiçbir şey için istisnalar yakalamayın. Ve eğer yaparsanız, sadece kullanarak yeniden düşünün throw;.


5
Ben de bu amaçla Object.ReferenceEquals (obj, null) gördüm . Eşitlik geçersiz kılmalarını önlemek mi?
Luca

2
: Jenerikleri kullanırken @LucaPiccioni ben önlemek için kullandım değer tipi-şikayet geekality.net/2009/11/13/generics-and-checking-for-null
Svish

4
Ben tercih ederim null != data. Sabiti ilk olarak koymak, bonehead yazım null = datahatasını kasıtsız bir atama yerine bir derleyici hatasına dönüştürür. (Ayrıca çalışır ==.)
jpmc26 27:08

6
@ jpmc26: C # ' if (data = null)da zaten bir derleme zamanı hatasıdır, bu yüzden oraya gitmek onlarca yıl sürse bile, artık buna dikkat etmemize gerek yoktur. C ++ derleyicileri bile bu kod için olası istenmeyen atamalar hakkında kolayca uyarı verecektir.
Jon

Luca, testte 'nesneye' döküm yaparak eşitlik geçersiz kılmalarından da kaçınabilirsiniz. Benzer bir şekilde, bu cevap bunun yerine şunu iddia etmelidir: "if ((object) data! = Null)" çünkü eşitlik geçersiz kılındığında hatalardan kaçınır.
DAG

82

C #> 7.0 kullanımında

if (obj is null) ...

Bu, nesne tarafından tanımlanan herhangi bir == veya! = Yok sayacaktır (elbette bunları kullanmak istemiyorsanız ...)

Geçersiz kullanım için if (obj is object)(veya if (!(obj is null)))


1
Acaba bir "boş değil" var mı? (piton söyleyebilirim obj is not null)
sehe

1
Neden daha okunabilir (obj! = Null) daha iyi
Orn Kristjansson

39
Uygulamalarını isterdim if (obj aint null):(
Nick Bull

10
Çünkü boş değilif (obj is object)
yatskovsky

3
@OrnKristjansson çünkü! = Ve == geçersiz kılınabilir.
mitchellJ

61

C # 6 monadic null kontrol var :)

önce:

if (points != null) {
    var next = points.FirstOrDefault();
    if (next != null && next.X != null) return next.X;
}   
return -1;

sonra:

var bestValue = points?.FirstOrDefault()?.X ?? -1;

7
Çünkü "yorumlar yalnızca 5 dakika boyunca düzenlenebilir"? Ne? Her neyse ... Başlarken ... Buraya daha iyi bir sözdizimi aramaya geldim result = myObject == null ? null : myObject.SomePropertyve örneğin yazmam için beni eğlendirdi result = myObject?.SomeProperty. Adam!! Sinsi. Kodlamayı hala seviyorum ...
Adam Cox

27

VeriListeniz, yayınladığınız koda bakarak, somutlaştırılmadığı için boş.

Deneyin:

public List<Object> dataList = new List<Object>();
public  bool AddData(ref Object data)
bool success = false;
try
{
    if (!data.Equals(null))   // I've also used if(data != null) which hasn't worked either
    {
       dataList.Add(data);                      //NullReferenceException occurs here
       success = doOtherStuff(data);
    }
}
catch (Exception e)
{
    throw new Exception(e.ToString());
}
return success;

}


3
Ayrıca, sadece eklemek için, veriler null ise, çökmez, <Object> Listesine null ekleyebilirsiniz.
DaveShaw

7
Ama yapmaya çalışmak Boş olan eşyalar istisna oluşturur. Yapmalı! = Boş
glosrob 20:11

@glosrob: Ah !! Ne gözetim! NullReferenceException nesneden olduğunu düşünüyordum .. liste değil! C # için yeni ve c # null için kontrol özel bir yol olduğunu düşündüm!
geliştirici 21

Bu da, ama Ed S.'nin bunu örtmüş olduğunu gördüm.
DaveShaw

1
@DaveShaw: Uyarı için teşekkürler. Ben yine de bir kontrol yapacağım, ancak daha sonra işlenmek üzere eklenen bir boş nesne önlemek istiyorum. :)
geliştirici 21

19

[@ Kelton52 tarafından ipucu yansıtacak şekilde düzenlendi]

Bunu yapmanın en basit yolu object.ReferenceEquals(null, data)

Yana (null==data)işin garanti DEĞİLDİR:

class Nully
{
    public static bool operator ==(Nully n, object o)
    {
        Console.WriteLine("Comparing '" + n + "' with '" + o + "'");
        return true;
    }
    public static bool operator !=(Nully n, object o) { return !(n==o); }
}
void Main()
{
    var data = new Nully();
    Console.WriteLine(null == data);
    Console.WriteLine(object.ReferenceEquals(null, data));
}

üretir:

'' İle 'Nully' karşılaştırması

Doğru

Yanlış


1
Aslında bunu denedim ve 'Zımni avantaj, veri sınıfında "operatör! =" Gibi geçersiz kılmaları görmezden gelmesidir. Gerçek gibi görünmüyor.
Kelly Elton

9

Hayır, kullanmalısın !=. Eğer datagerçekte null sonra program sadece kilitlenmesine NullReferenceExceptionarama girişiminde sonucu Equalsüzerine yöntemini null. Ayrıca, özellikle referans eşitliğini kontrol etmek istiyorsanız, Object.ReferenceEqualsyöntemi nasıl kullanacağınızı asla bilmediğinizden emin olun.Equals uygulandığını .

Programınız çöküyor çünkü dataListhiç başlatmadığınız için boş.


7

Bu durumda sorun databoş değil . O olmasıdır dataListkendisi boş.

Bildirdiğiniz yerde dataListyeni bir Listnesne oluşturmalı ve değişkene atamalısınız.

List<object> dataList = new List<object>();

5

@Jose Ortega cevabına ek olarak , kullanım uzantısı yöntemi için daha iyi

 public static bool IsNull(this object T)
     {
        return T == null;
     } 

Ve aşağıdaki IsNullgibi tüm nesneler için yöntem kullanın :

object foo = new object(); //or any object from any class
if (foo.IsNull())
   {
     // blah blah //
   }

1
Neden return T == null ? true : false; ve sadece return T == null;?
md2perpe

1
Kabul ettiğimden emin değilim. Bir nesne üzerinde null olup olmadığını kontrol etmek için bir yöntem çağırmak garip görünüyor. Bunun bir uzantı yöntemi olduğunu bilmeden, boş bir referans istisnası atacağını düşünürdünüz.
Jamie Twells

Jamie'nin doğru olduğunu tamamen doğrulayabilir - bu işe yaramaz. Ben tavşan beyinli bir an vardı ve benzer bir uzantısı yöntemi yazdı çünkü biliyorum: P Kod her zaman boş bir referans istisna attı, kesinlikle uzatma yöntemine gitmeyecek.
James King

Aslında ben bunu uzatma yöntemi ile bunu yapmak istiyorum söylemek istiyorum ... kod bazı sorun olabilir ve geliştirebilir!
Ali

Boş bir nesnede bir uzantı yöntemini çağırabilirsiniz; dikkatli olmak için T'yi (bu durumda) null ile karşılaştırmanız yeterlidir. Jamie haklı ama tuhaf görünüyor.
Tim Barrass

3

C # 8'den itibaren, bir nesnenin boş olmadığından emin olmak için 'boş' özellik desenini ( desen eşleşmesi ile ) kullanabilirsiniz :

if (obj is { })
{
    // 'obj' is not null here
}

Bu yaklaşım, " nesne bir şeyin örneğine başvuruyorsa " " (yani null değil) anlamına gelir.

Sen tersi olarak bu düşünebilirsiniz: if (obj is null).... nesne bir şeyin örneğine başvurmadığında true değerini döndürür.

C # 8.0'daki desenler hakkında daha fazla bilgi için burayı okuyun .


3

İtibariyle C # 9 Yapabileceğiniz

if (obj is null) { ... }

Geçersiz kullanım için

if (obj is not object) { ... }

Bu davranışı geçersiz kılmanız gerekiyorsa ==ve !=buna göre kullanın .


2

Jeffrey L Whitledge haklı. `DataList´-Object öğesinin kendisi boş.

Kodunuzla ilgili başka bir sorun daha var: ref-anahtar sözcüğünü kullanıyorsunuz, yani bağımsız değişken verileri boş olamaz! MSDN diyor ki:

Önce ref parametresine iletilen bir argüman başlatılmalıdır. Bu, argümanları geçilmeden önce açıkça başlatılmasına gerek olmayan dışarıdan farklıdır

Jenerikleri `` Object '' tipi ile kullanmak da iyi bir fikir değildir. Jenerikler boks / kutudan çıkmayı önlemeli ve aynı zamanda tip güvenliğini sağlamalıdır. Ortak bir tür istiyorsanız yönteminizi genel yapın. Son olarak kodunuz şöyle görünmelidir:

public class Foo<T> where T : MyTypeOrInterface {

      public List<T> dataList = new List<T>();

      public bool AddData(ref T data) {
        bool success = false;
        try {
          dataList.Add(data);                   
          success = doOtherStuff(data);
        } catch (Exception e) {
          throw new Exception(e.ToString());
        }
        return success;
      }

      private bool doOtherStuff(T data) {
        //...
      }
    }

2

Diğerleri zaten işaret gibi, o değil dataolasılıkla daha ziyade dataListolduğunu null. Buna ek olarak...

catch- throwneredeyse her gördüğümde kusmak istememi sağlayan bir antipattern. Bir şeyin derinlerde yanlış gittiğini düşünün doOtherStuff(). Eğer geri almak tek şey bir olduğu Exceptionatılan nesne, throwin AddData(). Hiçbir yığın izlemesi, çağrı bilgisi yok, durum yok, hiçbir sorun yok, eğer sorunun gerçek kaynağını göstermezseniz, girmeyin ve hata ayıklayıcınızı işlenmeyen istisna yerine atılan istisnadan kurtulamayacak şekilde değiştirin. Bir istisna yakalar ve herhangi bir şekilde yeniden atarsanız , özellikle try bloğundaki kod herhangi bir şekilde önemsizse, kendinize (ve iş arkadaşlarınıza, şimdiki ve geleceğinize) bir iyilik yapın ve tamamını atıntrycatch bloğu - bloğu . Kabul,throw;alternatiflerinden daha iyidir, ancak yine de kendinize (veya koddaki bir hatayı düzeltmeye çalışan herkes) tamamen gereksiz baş ağrıları veriyorsunuz. Bu, catch bloğunun içine atılan istisna nesnesiyle ilgili bir şey yaptığınız sürece, try-catch-throw'ın mutlaka kötü olduğu anlamına gelmez .

Sonra Exceptionilk etapta yakalamanın potansiyel sorunları var , ama bu başka bir mesele, özellikle bu özel durumda bir istisna attığınız için.

Bana biraz tehlikeli olmaktan başka bir şey de data, referansla geçtiğiniz için işlevin yürütülmesi sırasında potansiyel olarak değeri değiştirebileceğidir. Bu nedenle null kontrol geçebilir, ancak kod değerle herhangi bir şey yapmaya başlamadan önce değiştirilir - belki de null. Bu bir endişe ya da değil (ben olmayabilir) olumlu değil, ama dikkat etmeye değer gibi görünüyor.


2
  public static bool isnull(object T)
  {
      return T == null ? true : false;
  }

kullanın:

isnull(object.check.it)

Koşullu kullanım:

isnull(object.check.it) ? DoWhenItsTrue : DoWhenItsFalse;

Güncelleme (başka bir yol) 31.08.2017 tarihinde güncellendi. Yorum için teşekkürler.

public static bool isnull(object T)
{
    return T ? true : false;
}

5
cond ? true : false;tamamen adil cond. Bu hiçbir şey katmıyor.
lericson

Üzgünüm ama işlevi kontrol ederseniz bool değeri döndürmelidir. Formalizmi yapıyorum. Tekrar kontrol et
Jose Ortega

3
O anlamına return T == null;da bir boolean döndürür!
MQoder

Ne dediğini biliyorum. ty
Jose Ortega

1
return T == null ? true : false;Sadece kullanmak yerine return T == null;.
md2perpe

1

Sınıf nesneleri oluşturduğunuzda, aşağıdaki kodu kullanarak nesnenin boş olup olmadığını kontrol etmeniz gerekir.

Örnek: object1, sınıf nesnesidir

void myFunction(object1)
{
  if(object1!=null)
  {
     object1.value1 //If we miss the null check then here we get the Null Reference exception
  }
}

0

Sadece java betiğinde genellikle takip ettiğimiz bir yöntemi izledim. Nesneyi dizeye dönüştürmek ve sonra null olup olmadığını kontrol etmek için.

var obj = new Object();
var objStr = obj.ToString();
if (!string.IsNullOrEmpty(objStr)){
  // code as per your needs
}

0

Daha basit (olumlu bir şekilde) yaptım ve iyi çalışıyor gibi görünüyor.

Her türlü "nesne" en azından bir nesne olduğu için


    if (MyObj is Object)
    {
            //Do something .... for example:  
            if (MyObj is Button)
                MyObj.Enabled = true;
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.