簡體   English   中英

C#泛型:我如何一般地使用它們?

[英]C# Generics: How can I use them generically?

[TestMethod]
public void TestMyGenericBaseClasses()
{ 
    Type typeCrazy = ThisPartyIsTypeCrazyWOOT();

    // How do I create a generic object?
    MadnessOhYeah<typeCrazy> sanity = new MadnessOhYeah<typeCrazy>();

    // How do I use a generic object after it has been created?
    Assert.IsTrue(sanity.MyTrueFunction(), "this is sparta");

    // How do I call a generic function generically?
    bool result = MyFunction<typeCrazy>();

    Assert.IsTrue(result, "I did not get my teeth whitened!");

}

有沒有辦法讓這個編譯? (ThisPartyIsTypeCrazyWOOT返回一個Type)因為這是一個測試,我們不關心必須使用反射或任何東西,除非那只是絕對瘋狂。

我正在獲得這種不可能的氛圍,而且我們的測試功能必須更加具體。

更新2 :我發布的第一個示例仍然沒有100%回答這個問題,因為它涉及到Cast List<int>的強制轉換,這是一種在編譯時已知的類型。 以下是說明了如何使用泛型類型一無所知對類型參數本身只反射的解決方案。 但是,正如你所看到的,它是......好吧,惡心;)

Type userType = GetUserSuppliedType();

// Now let's say userType is T.
// Then here we are getting the type typeof(List<T>).
// But, of course, there's no way to have any such information in the code.
Type listOfUserType = typeof(List<>).MakeGenericType(new[] { userType });

// This is effectively calling new List<T>();
object listObject = Activator.CreateInstance(listOfUserType);

// Do you see how messy this is getting?
MethodInfo addMethod = listOfUserType.GetMethod("Add");

// We better hope this matches userType!
object input = GetUserSuppliedInput();

// I suppose we could check it, to be sure...
if (input == null || input.GetType() != userType)
{
    throw new InvalidOperationException("That isn't going to work!");
}

// Here we are finally calling List<T>.Add(input) -- just in the most ass-
// backwards way imaginable.
addMethod.Invoke(listObject, new[] { input });

更新 :好的,如果你堅持這樣做,這里有一個例子說明它是如何可能的 - 但非常麻煩!

Type genericListType = typeof(List<>);
Type listOfInt32Type = genericListType.MakeGenericType(new[] { typeof(int) });

object listObject = Activator.CreateInstance(listOfInt32Type);

List<int> list = (List<int>)listObject;

list.Add(1);

泛型不能像這樣工作,因為Type對象可以是任何東西。 考慮以下代碼:

var list = new List<int>();
list.Add(1);

上面代碼中的list類型已知為List<int> ,它定義了list上合法的操作,例如Add(1)

現在考慮一下:

Type t = GetTypeFromIndeterminateSourceSuchAsUserInput();
var list = new List<t>();
list.Add(?);

t是一個Type對象而不是編譯器可以解析的類型(如int )的名稱時 ,實際上不可能使用該類型實例化泛型類型 - 或者更確切地說,它是可能的 (參見Andrey的答案 ),但你可以我真的以任何通用的方式使用結果對象。

現在,您可能會認為這樣的事情應該有效:

Type t = typeof(int);
var list = new List<t>();
list.Add(1);

...但是因為在編譯時t (你)知道t的值並不會改變一般工作的方式。

無論如何,是的,可以使用反射; 但是如果你沿着這條路走下去,那么你就會致力於一個反思很重的解決方案。 我所得到的是,一般來說這不是一件特別現實的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM