我有带有通用T1的Class1和带有通用T2的Class2。通用T2有约束,而T1没有约束。
现在在Class1中,我想检查T1是否与T2的约束匹配,以及是否与Class2一起使用。
这可能吗?怎么样?
public class Class1<T1> {
public static object GetObj() {
if (typeof(SomeBaseClass).IsAssignableFrom(typeof(T1))) {
// I know that T1 is a subclass of SomeBaseClass, and want to create a Class2 object using it
return new Class2<T1>(); // this doesn't work. How can I "force" the compiler to treat T1 as a T2, like casting?
}
}
}
public class Class2<T2> where T2 : SomeBaseClass {
}
编辑:不幸的是,由于开销,反射不是一个好的解决方案,这被称为很多。
最佳答案
正如@AakashM所说,我想使用反射是唯一的方法:
public class Class1<T1>
{
public static object GetObj()
{
if (typeof(SomeBaseClass).IsAssignableFrom(typeof(T1)))
{
var genericType = typeof(Class2<>).MakeGenericType(typeof(T1));
return Activator.CreateInstance(genericType);
}
// throw Exception or return null
}
}
更新资料
发表您的评论后,如果反射太慢,则可以使用编译表达式:
public class Class1<T1>
{
private static readonly Func<T1> _factory;
static Class1()
{
if (!typeof(SomeBaseClass).IsAssignableFrom(typeof(T1)))
{
_factory = () => default(T1);
return;
}
var ctor = typeof(T1).GetConstructor(Array.Empty<Type>());
var newExpression = Expression.New(ctor);
_factory = Expression.Lambda<Func<T1>>(newExpression).Compile();
}
public static object GetObj()
{
return _factory();
}
}
此解决方案为
Class1
的每个变体(例如Class1<SomeSubClass>
,Class1<SomeOtherSubClass>
等)创建一个工厂。构建表达式需要一些时间,但是之后确实非常快。我已经进行了一些测试,以查看使用
Class2
方法创建一百万个GetObj()
实例需要花费多长时间:最佳情况(将约束添加到
Class1
,只需返回new Class2<T1>()
):4毫秒反射(如原始解决方案所示):991毫秒
使用已编译的表达式(如上所示):26 ms
如您所见,新解决方案比以前的解决方案快得多。但是,如果您为
T1
使用许多不同类型,则性能提升将变小甚至不存在。关于c# - 泛型用作更具体的泛型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40108632/