Null verildiğinde neden operatör yanlış döndürüyor?


135

Bana öyle geliyor ki isoperatör biraz tutarsız.

bool Test()
{
    // Returns false, but should return true.
    return null is string;
}

Biri, nulldeğerin herhangi bir referans (veya boş değer) türüne ait olmasını bekler . Ve gerçekten de, C # dil belirtimi bu hipotezi destekleyen bir şey söylüyor, örneğin (6.1.6 Örtük referans dönüşümleri):

Örtük referans dönüşümleri şunlardır:
...
• Boş değerden herhangi bir başvuru türüne.

Açıklaması (7.10.10 olan operatör) isifadesi olduğunu söyleyerek operatör başlar (E is T)bir referans dönüşüm zaman gerçek neden olacaktır Eiçin Tvar, ancak daha sonra yazarlar zaman açıkça davayı hariç tutarak gitmek Eolduğunu nullliteral veya sahiptir nulldeğeri .

Bunu neden yapıyorlar? Bana göre mantıksız görünüyor.


Neden açıkça null dışlanmışlar programmers.stackoverflow.com için en iyi soru
Miserable Variable

2
Yakın oyumu iptal edemiyorum, ancak bu sorular burada iyi: meta.stackexchange.com/questions/36850/…
Merlyn Morgan-Graham

Java null typeof Objectda yanlış döndürür
cırcır ucube

Varsayın null is stringvardı trueve bu ima nullbir olduğunu string. Ayrıca farz null is Nullable<int>olan trueima nullbir olduğunu Nullable<int>. Şimdi bu soruya cevap verin: ne tür null?
CVn

1
@Michael Kjörling: Sıralı değil. Bahsedilen gerçeklerden (null bir dize, null bir Nullable <int>) bu soruyu cevaplayabilmem gerektiği izlenmiyor.
Gebb

Yanıtlar:


195

Bu soru 30 Mayıs 2013'teki blogumun konusuydu . Bu mükemmel soru için teşekkürler!


Boş bir araba yoluna bakıyorsunuz.

Birisi size "Araba yolunuz Honda Civic tutabilir mi?"

Evet. Evet yapabilir.

Birisi sizi ikinci bir yola yönlendiriyor. Ayrıca boş. "Araba yolumun mevcut içeriği araba yolunuza sığabilir mi?"

Evet, tabii ki. Her iki yol da boş! Birinin içeriği diğerine sığabilir, çünkü her ikisinin de içeriği yoktur.

Birisi size "Araba yolunuz Honda Civic içeriyor mu?"

Hayır.

isOperatörün ikinci soruyu cevapladığını düşünüyorsunuz : bu değer göz önüne alındığında, bu tür bir değişkene uyuyor mu? Bir boş başvuru bu tür bir değişkene uyuyor mu? Evet öyle.

isOperatörün cevapladığı soru bu değil . Bu soruyu isoperatörü cevaplar üçüncü sorudur. y is Xsormuyor " olan ytürde bir değişkenin yasal değeri X? " Bu "sorar ytüründe bir nesne için geçerli bir referans X? " null başvuru için geçerli bir referans olmadığı için herhangi bir nesne herhangi türü, cevap hayır" dır ". Bu araba yolu boş; Honda Civic içermiyor.

Buna bakmanın bir başka yolu da şu y is Xsoruya cevap vermesidir "dedim y as X, boş olmayan bir sonuç elde eder miydim?


Sorunuza biraz daha derin bakmak için:

Biri, null değerinin herhangi bir başvuru (veya null edilebilir) türüne ait olmasını bekler

Bir türün bir değer kümesi olduğu ve y değerinin X tipindeki bir değişkenle atama uyumluluğunun y'nin x kümesinin bir üyesi olup olmadığını kontrol etmekten başka bir şey olmadığı varsayılır .

Bu, türlere bakmak için son derece yaygın bir yol olsa da, türlere bakmanın tek yolu bu değildir ve C #, türlere bakmanın yolu değildir. Boş başvurular C # türünde olmayan türlerdir; atama uyumluluk edilir değil sadece bir değer içermesi olmadığını görmek için bir dizi kontrol ediyor. Bir null referansın, X referans tipi bir değişkenle uyumlu atama olması, null'un X tipinin bir üyesi olduğu anlamına gelmez. "" Atama ile uyumlu atamadır ve "tipin bir üyesidir" ilişkisinin çok fazla örtüşüyor, ancak CLR'de aynı değiller.

Eğer tip teorisi hakkındaki düşünceler ilginizi çekiyorsa, konuyla ilgili son makalelerime göz atın:

"Tip" olarak adlandırdığınız bu şey nedir? Bölüm Bir

"Tip" olarak adlandırdığınız bu şey nedir? Bölüm iki


@Gebb: Yardım etmekten mutluluk duyuyorum. Bu makale de ilginizi çekebilir
Eric Lippert

Eric bunu bir blog yayınına dönüştürdü: ericlippert.com/2013/05/30/what-the-meaning-of-is-is
Kevin Cathcart

y is X" ytür değişkeninin yasal değeri Xmidir?" sorusunu sormaz. "Türdeki ybir nesneye geçerli bir başvuru var mı X?" Bütün mesele buydu! Teşekkürler!
Jalal

Ama sorarsam y is int?, o zaman "Araba yolunuz Honda Civic içeriyor mu yoksa hiçbir şey içeriyor mu?" Araba yolunuz boşken cevap hala neden hayır? Kaputun altına bakarsanız daha da kötüleşir, çünkü soru "Araba yolunuz bir Honda Civic veya 'Burada Honda Civic yok' yazan bir işaret içeriyor mu?" Araba yolunuzda belirtilen işaret olsa bile, cevap hala hayır.
Faks

1
@Gerard: Uzun, ayrıntılı, konuşkan cevaplar verdiğimde insanlar bana daha kısa olmaları gerektiğini söylüyorlar. Kısa ve özlü cevaplar verdiğimde insanlar bana daha uzun olmaları gerektiğini söylüyor. Sonuç: insanlar şikayet etmeyi sever. Sekiz yaşındaki bu soruya neyin iyi bir cevap verdiğine dair hisleriniz olduğu için önerim, kendimizi cevaplayarak neyin iyi bir cevap verdiğini bize göstermeniz, böylece öğrenebiliriz.
Eric Lippert

24

null is stringYanlış döndürmenin çok sezgisel olduğunu düşünüyorum . Null hiçbir şey ifade etmez ve kesinlikle bir dize değildir. Bu yüzden yanlış dönmelidir. Dil tasarımcılarının yaptığı bir seçim olsa da, null'un gerçek dünya anlamını düşündüğünüzde çok sezgisel bir seçimdir.


2
+1 çünkü soru gerçekten sezgisel olup olmadığı ve OP'nin zaten farkında olduğu spesifikasyonu sorgulamadığıyla ilgilidir. İngilizce bir cümle olarak sorarsanız " nullbir dizedir" cevabı hayır, değil, "farklı" nullatanabilir string"
Davy8

null is stringoldukça sezgiseldir, (string)null is stringC # 'da null referansın nasıl çalıştığını gerçekten bilmiyorsanız bir duraklama gerekebilir.
decPL

24

nullHazır atanabilir herhangi bir referans türü. Kendi içinde bir tür değildir . Bu özel hazır temsil Boş bir başvuru.

A'nın isgeçeceği truezaman geri dönecek olması durumunda null, nullkelimenin tam anlamıyla ne yapabilirdiniz ? Hiçbir şey - öyle null. trueKafa karıştırıcı meseleler dışında bunun geri dönüşü ne olurdu ?


Ne olursa olsun - ne kadar sezgisel olarak, kodu İngilizce olarak okuyun ve bana söyleyin:

null is string;

Bunu gördüğümde, soruyu soruyor gibi görünüyor is "nothing" a string?. Sezgim bana hayır olduğunu söylüyor, değil - öyle nothing.


Sorun deđil, ama sonra bir ip de, deđil mi? Peki (null is string)o zaman neden geri dönüyor?
Gebb

Başka türlü ifade ederdim. Herhangi bir referans türü boş olabilir. null sadece null.
Mark H

@Oded, null değeri, örneğin nesne türünün geçerli bir değeri mi? Bu tür bir değişkene atayabilirim, değil mi? Bu yüzden cevap evet gibi görünüyor, değer tamamen geçerli ve tahminim (null is object)ifadenin tam olarak bunu kontrol etmesi gerektiğidir.
Gebb

@Gebb: ValueTypes öğelerinin de nesne olduğunu unutmayın, ancak başvuru türleri değildir.
Mark H

1
@Oded: "Kafa karıştırıcı meseleler dışında bunun doğru dönmesinin anlamı ne olurdu?" Aslında, dili daha mantıklı kılacaktır. Şu iki noktayı göz önünde bulundurun: (1) isbir referans (burada başka tür dönüşümlere ihtiyacımız yok) dönüşümünün olup olmadığını kontrol eder; (2) nullherhangi bir referans türüne dönüştürülebilir. Bu nedenle (null is T), T'nin başvuru türü olduğu durumlarda true döndürmelidir. Ama hayır, burada açık bir istisnamız var, bu benim için kafa karıştırıcı görünüyor.
Gebb

12

http://msdn.microsoft.com/en-us/library/scekt9xw%28v=vs.71%29.aspx

İs ifadesi, aşağıdaki koşulların her ikisi de karşılandığında doğru olarak değerlendirilir:

  • ifade boş değil.
  • ifade türüne dökülebilir. Yani, formun (tür (ifade) bir cast ifadesi istisna olmadan tamamlanır.Daha fazla bilgi için, bkz: 7.6.6 Cast ifadeleri.

1
Her neyse, belgeler sadece ifadenin boş olamayacağını (zaten bildiğimizi) belirtir, ancak nedenini söylemez
kullanıcı adı

Neden başka bir şekilde istesin ki?
Sefil Değişken

1
@username: Bu yanıt, mekanik olarak çalışma şeklini açıklar ve size çalışmanız için bir model veren bir referans verir. Burada evrenin anlamını soruyorsun. Sanırım bizim tanrımız SO sık sık şanslısın;)
Merlyn Morgan-Graham

10

Pratik bir konu olarak, "null is T == false" olması ekstra kod yazmama engel olur:

Söylemek yerine

if (X != null && X is Foo) {}

Sadece söyleyebilirim

if (X is Foo) {}

ve onunla yapılabilir.


8

nulldeğer

Bunu sorunuzdan alıntıladım çünkü sorunun özüne inmiş gibi görünüyor. bir değer null değil - bir değerin yokluğu. isBenim amacım şu soruyu cevaplamak gibi görünüyor:

Ben dökme Eğer Eiçin T, ben başarıyla alacak T?

Şimdi, ise edebilir döküm nulliçin T hatasız bunu yaptıktan sonra, yok "ye sahiptir Thala var hiçbir şey -". O böyle değil Yani null"is" a T, yani isfalse döndürür.


3

Java'da orada tam olarak aynı şeyi yapar bir operatör, ama çok daha uzun bir adı vardır: instanceof. Orada null instanceof Stringyanlış döndüren çok sezgisel , çünkü null hiçbir şeyin örneği değil, çok daha az a String. Yani, nullJava'nın sürümünü kullanırken biraz daha sezgisel.

Ancak, her iki işleç de tüm hiyerarşiye bakması istendiğinde true değerini döndürür. Örneğin. örneği Stringbir Object. Ve işte ve C # (bir örnek aslında bir çok özel tip olduğu için) 's daha az sezgisel bit olduğunu Java var is(her çünkü daha sezgisel String olan bir Objectiçten içe).

Alt satır: bir kelimede oldukça gelişmiş mantığı tarif etmeye çalışırsanız, bu şekilde veya başka şekilde birkaç kişinin kafasını karıştırmanız gerekir. Görünüşe göre çoğu insan bir anlam üzerinde hemfikirdi ve hemfikir olmayanlar uyum sağlamak zorunda kaldılar.

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.