2011-11-20 74 views
50

D 耳朵全部,我想知道在C#中文字null的類型是什麼?什麼是空文字的類型?

在Java中,null文字is of the special null type

還有一個特殊空型,表達null,它沒有名字的類型。因爲null類型沒有名稱,所以不可能聲明null類型的變量或轉換爲null類型。空引用是空類型表達式的唯一可能值。空引用總是可以轉換爲任何引用類型。

在C++ 11,有nullptr,其is of type std::nullptr_t(舊夥伴NULL的推薦版本)。

我搜索了關於C#的MSDN,但specification似乎沒有說任何關於這一點。

+3

我不會準確地描述空爲具有類型。 – ChaosPandion

+0

@ChaosPandion:那麼,在C#中不是_every_表達式有一個類型? – Vlad

+1

好吧,我顯然是錯的。 – ChaosPandion

回答

53

按照ECMA C# language specification

9.4.4.6 null文本:

的類型的空字面的是null類型(§11.2.7)。

11.2.7 null類型:

null文本(§9.4.4.6)的計算結果爲空值,它被用來 表示一個參考在任何物體或陣列不指向,或 沒有價值。空類型具有單個值,即空值爲 。因此,類型爲空類型的表達式只能計算爲空值。沒有辦法明確寫入空值類型,因此無法在聲明的類型中使用它。 此外,空類型不能被推斷爲 類型參數類型(§25.6.4)

因此,要回答你的問題,空是它自己的類型 - null類型。

雖然它是如何不在C# 4.0 language specificationC# 3.0 language specification提及,但在overview of C# 3.0提到它是奇數,則ECMA C# language specificationC# 2.0 language specification

+0

自嘆不如,你在這是不一樣的一個在MSDN文檔參考ECMA標準分:http://msdn.microsoft.com/en-us/library/ms228593.aspx – Vlad

+0

@Vlad這是相當有趣的,可能值得看看[Eric Lippert](http://blogs.msdn.com/b/ericlippert/)對此有何評論。 –

+0

我認爲,具有'null'的單獨類型的原因與Java/C++相同。不知道爲什麼這沒有找到它的方式進入MSDN。 – Vlad

42

更新:This question was the subject of my blog in July 2013.感謝您的好問題!


J.Kommer的答案是正確的(和好對他們做什麼,顯然被不少規格挖的!),但我想我會加一點歷史的角度。

當Mads和我正在整理C#3.0規範的各個部分的確切用詞時,我們意識到「空類型」是奇怪的。這是一個只有一個值的「類型」。這是Reflection對反應一無所知的「類型」。它是一個「類型」,沒有名稱,GetType永不返回,你不能指定爲局部變量或字段或類型的類型。簡而言之,它確實是一種「類型」,它只是爲了使類型系統「完整」,以便每個編譯時表達式都有一個類型。

除了C#已有表達式沒有類型:方法組在C#1.0,​​在C#2.0匿名的方法和在C#3.0的lambda都沒有類型。如果所有這些東西都沒有類型,我們意識到「null」也不一定有類型。因此我們刪除了對C#3.0中無用的「空類型」的引用。

作爲一種實施細節,C#1.0到5.0的所有Microsoft實現並有一個內部對象來表示「空類型」。他們還有對象來表示不存在的lambda表達式,匿名方法和方法組。這種實施選擇有許多優點和缺點。在專業方面,編譯器可以詢問任何表達式的類型並獲得答案。另一方面,這意味着類型分析中的錯誤有時會使編譯器崩潰,而不是導致程序中的語義更改。我最喜歡的例子是它可能在C#2.0中使用非法表達式「null ?? null」;由於缺陷,編譯器無法將其標記爲??運算符的錯誤用法,並繼而推斷該表達式的類型是「空類型」,即使該類型不是空文字。隨着類型分析器嘗試理解類型,這會導致許多其他下游錯誤。

在羅斯林,我們可能不會使用這個策略;相反,我們只是簡單地將編譯器實現中的某些表達式沒有類型。

+2

我希望Roslyn能夠詢問任何表達式的類型,併爲所有這些非類型類型添加類型定義。你還會怎麼回答這個問題:「null表達式是什麼類型?」 – configurator

+0

@Eric:但微軟官方的職位是什麼? 'null'表達式是否有類型? (如果不是這樣,考慮到lambda等沒有類型,可能並不奇怪。) – Vlad

+6

@ Vlad:C#3的官方位置。0是「null」沒有類型。 –

0

儘管不具有運行時類型的,null可以轉換爲一個類型在編譯時,如本例所示。

在運行時,你可以找到該變量stringAsObject持有string,不僅object,但你找不到任何類型的變量nullStringnullStringAsObject

public enum Answer { Object, String, Int32, FileInfo }; 
private Answer GetAnswer(int i) { return Answer.Int32; } 
private Answer GetAnswer(string s) { return Answer.String; } 
private Answer GetAnswer(object o) { return Answer.Object; } 

[TestMethod] 
public void MusingAboutNullAtRuntimeVsCompileTime() 
{ 
    string nullString = null; 
    object nullStringAsObject = (string)null; 
    object stringAsObject = "a string"; 

    // resolved at runtime 
    Expect.Throws(typeof(ArgumentNullException),() => Type.GetTypeHandle(nullString)); 
    Expect.Throws(typeof(ArgumentNullException),() => Type.GetTypeHandle(nullStringAsObject)); 
    Assert.AreEqual(typeof(string), Type.GetTypeFromHandle(Type.GetTypeHandle(stringAsObject))); 
    Assert.AreEqual(typeof(string), stringAsObject.GetType()); 

    // resolved at compile time 
    Assert.AreEqual(Answer.String, this.GetAnswer(nullString)); 
    Assert.AreEqual(Answer.Object, this.GetAnswer(nullStringAsObject)); 
    Assert.AreEqual(Answer.Object, this.GetAnswer(stringAsObject)); 
    Assert.AreEqual(Answer.Object, this.GetAnswer((object)null)); 
    Assert.AreEqual(Answer.String, this.GetAnswer((string)null)); 
    Assert.AreEqual(Answer.String, this.GetAnswer(null)); 
} 

// Uncommenting the following method overload 
// makes the last statement in the test case ambiguous to the compiler 
// private Answer GetAnswer(FileInfo f) { return Answer.FileInfo; }