C# 如何绕过编译器对C方法的“where”约束的验证

C# 如何绕过编译器对C方法的“where”约束的验证,c#,generics,dynamic,C#,Generics,Dynamic,我使用的库包含以下方法: T TheirMethod<T>() where T : Base; // T must inherit from Base T MyMethod<T>() // it can be any T here { if (!typeof(T).IsSubclassOf(typeof(Base))) throw new Exception("I'm fine with crashing at runtime here");

我使用的库包含以下方法:

T TheirMethod<T>() where T : Base; // T must inherit from Base
T MyMethod<T>() // it can be any T here
{
    if (!typeof(T).IsSubclassOf(typeof(Base)))
        throw new Exception("I'm fine with crashing at runtime here");
    return x.TheirMethod<T>(); // DOES NOT COMPILE
}
在我的代码中,有以下方法:

T TheirMethod<T>() where T : Base; // T must inherit from Base
T MyMethod<T>() // it can be any T here
{
    if (!typeof(T).IsSubclassOf(typeof(Base)))
        throw new Exception("I'm fine with crashing at runtime here");
    return x.TheirMethod<T>(); // DOES NOT COMPILE
}
当然这不会编译,因为编译器不够聪明,无法静态地证明我的t是一个基。 我无法向MyMethod添加where约束,因为它实现了另一个第三方接口

我的问题是:我怎么称呼它呢?我希望在运行时完成此检查。

使用特殊的动态类型,将类型约束检查延迟到运行时:

return ((dynamic)x).TheirMethod<T>();
我在写问题的中途找到了答案,但我还是把它贴出来,以防它对别人有用。

你可以用反射来调用这个方法。但是你应该考虑反射的性能影响。

T MyMethod<T>()
{
    if (!typeof(T).IsSubclassOf(typeof(Base)))
        throw new Exception("I'm fine with crashing at runtime here");

    return (T) typeof(TheirClass).GetMethod("TheirMethod").MakeGenericMethod(typeof(T)).Invoke(x, null);
}

为什么T可以是任何类型,如果它与除Base以外的所有类型崩溃?泛型的要点是能够使用通过约束的任何时间。在您的情况下,实际上根本没有任何约束,因此您的应用程序的客户端将假定他们可以传递任何类型,而他们在运行时获得一个eception。这完全打破了泛型的概念。顺便说一句:编译器足够聪明,不会让你自食其果。谁说动态不好?它实际上在一些特殊情况下非常有用。我们是说你用了一种不好的方式使用它。很明显,你有一些编译时类型,你用它来调用你自己的MyMethod。假设你这样称呼它:var t=MyMethod。在这里,您已经知道这在编译时是没有意义的。您无论如何都允许它,并让运行时处理这种情况。当然这是可能的。然而,这样做不是一个好主意。如果它破坏了您的代码库的其余部分,那么可能也需要修复。要么这样,要么进行重构,因为这里有一股巨大的代码味道。编译和运行都很好。。。如果你想了解原因,请在这里阅读:这是。。。与dynamic相同,只是它更难写和读。@eldritchcondrum不一样。dynamic必须加速DLR,它基本上是编译器的一个迷你版本。它必须编译方法,跟踪不同的调用站点和其他各种事情。那太贵了。反射也很昂贵,但考虑到选择,我认为我会放弃动态,即使它确实提供了一个看起来更干净的工作解决方案。