繁体   English   中英

运行时类型的编译时类型约束

[英]Compile-time type constraint for run-time type

我希望能够在编译时将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>();

编辑

我仍然不了解您需要的东西以外的其他东西。 即使它是其他类型的列表,也可以使用OfType<T>()使用Linq将其过滤为您感兴趣的类型。

[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");

为什么要使用泛型而不是仅定义要传入的接口或基类? 当您需要特定类型时,没有理由使用泛型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM