2013-11-01 25 views
1

昨晚我瞭解的casting by example這個奇妙的操作:一個非常酷的方式來產生使用到現有實例的引用某種類型的集合。鑄造集合的泛型隱含

我的問題是,雖然這一工程時,明確創建實例,如果使用活化劑從類型實例收集產生的類型是不準確的。

class TestCollectionContent 
    { 
     public int id { get; private set; } 
    } 

    [Test] 
    public void TestListCastCreation() 
    { 
     var explicitCast = new TestCollectionContent(); //This casts as TestCollectionContent 
     var explicitList = MakeList (explicitCast);   //This casts as List<CommandWithExecute> 
     explicitList.Add (new TestCollectionContent()); 

     Type clazz = typeof(TestCollectionContent); 
     var implicitCast = Activator.CreateInstance (clazz);//This casts as TestCollectionContent 
     var implicitList = MakeList (implicitCast);   //This casts as List<object> 
     implicitList.Add (new TestCollectionContent()); 

     Assert.AreEqual (explicitCast.GetType(), implicitCast.GetType()); //Succeeds 
     Assert.AreEqual (explicitList.GetType(), implicitList.GetType()); //FAILS! 
    } 

    public static List<T> MakeList<T>(T itemOftype) 
    { 
     List<T> newList = new List<T>(); 
     return newList; 
    } 

爲了我的目的,收集必須正確施放。有什麼想法嗎?

請注意,我在Unity3D中使用C#(它使用類似於.Net 3.5的東西)。

+0

我個人,我會避免這種行爲。總是更好地爲你需要的課程上課。 – gunr2171

+0

我正在構建框架的一部分。這是不可能的(實際上,與框架的前提相反)明確指定類。 – MarcT

回答

1

Activator.CreateInstance總是返回object,所以使用它時,你會不會從中得到任何靜態類型信息。這將使變量implicitCast類型object儘管它的值是一個更專業的類型。

現在,在使用泛型時,只考慮可用於靜態類型的類型。所以當通過implicitCastMakeList時,所有該方法看到的是object。因此,該方法將被稱爲MakeList<object>,並將返回一個List<object>,這當然不是與explicitList相同的類型。

不幸的是(或幸運的是?)你不能真的做得更好。泛型應該是在靜態類型環境中使用的東西,如果你開始動態地創建類型,你將失去這種能力。

你可以做這樣的事情但是使用Activator.CreateInstance爲列表創建一樣好:

public static IList MakeList(object itemOftype) 
{ 
    Type listType = typeof(List<>).MakeGenericType(itemOfType.GetType()); 
    return (IList) Activator.CreateInstance(listType); 
} 

當然,這也只是返回一個對象,所以你必須把它轉換爲更專用類型,或者使用非通用接口至少有一些訪問權限。

+0

謝謝你,捅!看起來它滿足我的用例就好! – MarcT

0

此代碼的行爲這種方式,因爲Tinferred在編譯時,不運行時間。由於implicitCast的類型爲object,因此它編譯爲MakeList<object>

var implicitList = MakeList (implicitCast); // equivalent to 
List<object> implicitList = MakeList<object>(implicitCast); 

var explicitList = MakeList (explicitCast); // equivalent to 
List<TestCollectionContent> explicitList = 
        MakeList<TestCollectionContent>(explicitCast); 

如果你想使用的運行時類型,你可以使用反射或dynamic