繁体   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