2012-10-26 24 views
2

所以這已經在S.O.上討論過了。然而之前我並不認爲我真的曾經看到過爲什麼會發生這種情況的解釋,也不能看出這對於普通開發人員試圖在其代碼中使用反射有什麼用處。關於c#泛型類型的維度信息有什麼好處

所以檢查這一點的代碼。

var fields = typeof(Person).GetFields(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance); 

如果我在Person對象有List<int>話,我會回來的場是誰的反思「名稱」設置爲List`1,或者如果我有一本字典它會Dictionary`2。表面上看來這使得它很難一起工作,我不能說這個出現以下

foreach (var fieldInfo in fields.Where(fieldInfo => fieldInfo.FieldType == typeof(List<int>))) 
{ 
    //Do something. 
} 

的原因是因爲我發現在一個項目我目前正在致力於以下。

//Initialize collections 
    FieldInfo[] properties = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance); 
    foreach (FieldInfo f in properties) 
    { 
     if (f.FieldType.Name == "IList`1" && f.GetValue(obj) == null) 
     { 
      object value = Container.Resolve(f.FieldType); 
      f.SetValue(obj, value); 

     } 
    } 

然後在統一配置我看到這種幸福

<alias alias="IList`1" type="System.Collections.Generic.IList`1, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> 

我真的不知道,我知道這是不好的?是嗎?它當然是有效的,但即使這是好的(這會導致我的可疑代碼dar熄滅),我的原始問題依然存在。關於泛型的維度信息對程序員有什麼好處呢?

+0

當你說「我不能說以下」。 ,你是什麼意思?這個循環如預期的那樣工作,沒有? – AakashM

+2

我不明白你的問題是什麼,你是問爲什麼,例如,'Tuple <>','Tuple <,>','Tuple <,,>'編碼(這是因爲它們是不同的類型,需要消歧) –

+0

我一直認爲編譯器生成的名稱可能會改變,IE,他們可能在未來的版本中有我t生成'IList-LOL \'1',並且突然你的代碼全部被破壞。 – Jasper

回答

2

當您處理編譯時已知的類型時,您不應該需要處理TypeName,因此名稱(如Thing`n)不應該成爲問題。

我不知道發生了什麼事在你的第一個例子,當我這樣做:

class Person 
{ 
    private List<int> intList; 
} 

這:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var fields = typeof(Person).GetFields(BindingFlags.DeclaredOnly 
              | BindingFlags.NonPublic 
              | BindingFlags.Instance); 

     foreach (var fieldInfo in 
      fields.Where(fieldInfo => fieldInfo.FieldType == typeof(List<int>))) 
     { 
      Console.WriteLine(fieldInfo.ToString()); 

     } 
    } 
} 

我得到了我所期望的,即

System.Collections.Generic.List`1[System.Int32] intList 

在給出的代碼示例中,再次在編譯時已知類型;比你出什麼是

​​

知道什麼IList<int>更好;您可以酌情使用IsAssignableFrom==

(如果你被IsAssignableFrom困惑,因爲我總是這樣,記住這一點:if (a is b)是相同的測試爲if (typeof(b).IsAssignableFrom(a.getType()))順序互換輪

+0

IsAssignableFrom是使所有這些都有用的關鍵。我知道你不能說:如果(theIntList.GetType()是typeof(列表)),但我不知道IsAssignableFrom。謝謝 – Kenn

3

這當然不是幫助程序員。它在那裏,因爲CLI需要它。有了進一步的基本原理,它可以確保具有相同標識符名稱但類型參數數量不同的泛型具有唯一的類型名稱。從ECMA 335規範一些措辭:

CLS第43條:一個通用類型的名稱應編碼對非嵌套類型中聲明,或新如果嵌套引入到型類型的參數的數量,根據上面定義的規則。 [注意:CLS(消費者):不需要消費違反此規則的類型。 CLS(擴展器):與消費者相同。選擇支持泛型類型定義的擴展器對於外部可見類型應遵循此規則。 CLS(框架):不應公開違反此規則的類型。注完]

隨着一些澄清部分II.9:

泛型類型包含一個名稱後跟一個<的......>泛型參數-delimited列表,如C<T>。在同一範圍內,兩個或更多的泛型不應該使用相同的名稱定義,而應該使用不同數量的泛型參數。但是,爲了允許在源語言級別對泛型進行重載,CLS規則43定義爲將泛型類型名稱映射到唯一的CIL名稱。該規則規定,具有一個或多個通用參數的類型C的符合CLS的名稱應該具有形式爲`n的後綴,其中n是十進制整數常量(不包括前導零),表示C具有的通用參數的數量。例如:類型C,C<T>C<K,V>分別具有符合CLS的名稱C,C 1<T>, and C 2<K,V>。 [注:所有標準庫類型的名稱都符合CLS;例如System.Collections.Generic.IEnumerable`1。注意]

對不起,沒有得到正確的方式,發表答案時,反引號是棘手的。看看ECMA文件的準確性。

+0

當您使用元組給出一個示例時,Kirk的評論確實會導致指示燈繼續亮起,但使用List <>進行測試時不太清楚,因爲就我而言知道你不能有一個列表或什麼(至少我從來沒有見過)。你回答清除它。然而,如果有人能夠評論他們在這個代碼庫中所做的事情的智慧(或缺少),那麼硬編碼「IList'1」然後創建統一映射 - 如果這是不好的決定,在那裏做什麼是正確的? – Kenn

+1

我不知道該代碼的目的,但它聞起來像一些hackorama在靜態類型很強的運行時環境中獲得動態綁定。 –

相關問題