编译运行时类型的时间类型约束
本文关键字:类型 约束 时间 编译 运行时 | 更新日期: 2024-10-22 07:26:00
我希望能够在编译时使用带有给定约束的System.Type;
有没有一种优雅的方法来解决这个问题?
internal abstract class BaseClass {}
internal class SubClass : BaseClass {}
internal class OtherClass {}
internal class Consumer
{
public void DoSomething(Type pType) {}
public void DoSomething(BaseClass pBaseClass) {}
public void DoSomething<tBaseClass>(tBaseClass pBaseClass) where tBaseClass : BaseClass {}
}
[TestFixture()]
public class TypeConstraintTest
{
[Test()]
public void TestCase1()
{
var lConsumer = new Consumer();
lConsumer.DoSomething(typeof (SubClass));
// This should not be allowed. Should have a type constraint.
lConsumer.DoSomething(typeof (OtherClass));
lConsumer.DoSomething(null as SubClass);
// This will generate a compiler error, but it's
// not an elegant solution, not easily readable/understandable.
lConsumer.DoSomething(null as OtherClass);
}
}
希望这个其他例子有助于澄清我的意图(如果不清楚,请道歉,因为我必须尽快写出来):
[TestFixture()]
public class ExampleTest
{
internal interface GroupingInterface {}
internal interface TargetInterface {}
internal class Class1 : GroupingInterface, TargetInterface {}
internal class Class2 : GroupingInterface {}
[Test()]
void TestCase()
{
var lGroup = new List<GroupingInterface>() { new Class1(), new Class2() };
foreach(var lClass in lGroup)
{
this.TestMethod(lClass.GetType());
// This works, but we are passing the object just for forcing the type.
// We are not going to use the object itself, so it would be better not
// To pass the reference to the specific object if there is a way...
this.TestMethodWithInstance(lClass);
// Don't know the type at compile-time as it is variable.
//this.TargetMethodWithGeneric<???>
// Ideally, there should be something like a generic "variable" method:
//this.TargetMethodWithGeneric<typeFrom(lClass)>
// This should give a compiler error as a GroupingInterface is not a TargetInterface.
// But, if we pass any TargetInterface subtype it should compile.
}
}
void TestMethod(Type pType)
{
// At this point, we want to make sure pType is
// a subtype of TargetInterface at compile-time.
// SHOULD NOT BE AT RUNTIME, SHOULD NOT COMPILE IF WRONG TYPE PASSED:
if (pType.GetInterfaces().Contains(typeof (TargetInterface))) throw new Exception();
}
void TestMethodWithInstance(TargetInterface pClass)
{
var lSubType = pClass.GetType();
// Do something with the type...
}
void TargetMethodWithGeneric<tType>() where tType : TargetInterface
{
// Do something with tType.
}
}
在编译时,实际上没有一种方法可以满足您的要求。System.Type
是预期和给定的类型,但是,对于您的泛型,我认为它正是您想要的解决方案。通常情况下,无论如何都不会将null直接传递给方法,它将是某种类型的变量,从而消除强制转换的要求。如果您尝试执行的操作实际上不采用参数,而仅采用类型,则可以更改定义以更好地匹配。
public void DoSomething<tBaseClass>() where tBaseClass : BaseClass
{
}
那么调用者只需要指定类型。
lConsumer.DoSomething<OtherClass>();
编辑
我仍然不明白除了你所拥有的以外还有什么需要。即使它是其他类型的列表,也可以使用Linq将其过滤为您感兴趣的类型,使用OfType<T>()
。
[Test()]
public void TestCase()
{
var lGroup = new List<GroupingInterface>() { new Class1(), new Class2() };
// If you know you need to extract classes of a certain type you can use this:
foreach (var lclass in lGroup.OfType<TargetInterface>())
{
// using OfType means lclass is already cast as the type expected, if the object is not of that type it will not be iterated
TestMethodWithInstance(lclass);
}
}
您是否正在寻找运行时检查:
if( !typeof(BaseClass).IsAssignableFrom(t) )
throw new Exception("Must be BaseClass derivative");
为什么要使用泛型,而不是只定义要传入的接口或基类?当您需要特定类型时,没有理由使用泛型。