繁体   English   中英

通用类型约束检查

[英]Generic type constraint checking

是否有可能在调用这些方法之一时编写在编译或运行时(即以任何方式)失败的东西?

public static void Register<TInterface, TImplementation>()
    where TImplementation : class, TInterface
{
}
public static void RegisterRestrictive<TInterface, TImplementation>()
    where TInterface : class
    where TImplementation : class, TInterface
{
}

以下将通过两个例子:

public interface IInterface
{
}

public class Implementation : IInterface
{
}


public void Test()
{
    Register<IInterface, Implementation>();
    RegisterRestrictive<IInterface, Implementation>();
}

我不认为是,因为你不能扩展结构?

因为这个https://github.com/aspnet/DependencyInjection/pull/624

问题是,据我了解:

class C<T, U> where T : class, U where U : class { }
class D<T, U> where T : class, U { }

是否存在对D而言合法的结构对C不合法

如果UT封闭类型 ,则不是。 也就是说,其中没有类型参数的类型。 正如Jon Hanna的回答指出的那样, 开放式可能会导致问题:

class N<T, U> where T : class, U { C<T, U> c; D<T, U> d; }

D的限制没有得到满足,因此这种结构是非法的。

对于封闭类型的类型参数,我们可以推断如下:

C ,约束要求U是引用类型。

DT可以是类,接口,委托或数组。 在任何情况下, U必须是相同T ,或基类的T ,或东西T可转化为经由(可能变体)隐式引用转换。 无论如何, U是参考类型。

请注意,无论是C#编译器,CLR验证器还是JIT编译器都不需要推断出U始终是一个引用类型! 例如,在这种情况下,C#编译器会对U用法生成不必要的装箱指令,即使您和我知道U不会是正在构造的值类型。

这可能导致U被装箱然后立即取消装箱的情况,以及我最后一次检查 - 这是,呃,十年前 - 抖动没有为该场景生成最佳代码。 毫无疑问,自从我上次检查以来,抖动已被重写了一次或多次,你可能不应该接受我的话。

这里的好习惯是将约束放在那里并拼出来。


一些有趣的相关事实:

你可以通过拉扯类似的恶作剧来进入类似的情况

class B<T> { public virtual void M<U>(U u) where U : T {} }
class D : B<int> { public override void M<U>(U u) { } }

请注意,C#不允许您重新声明约束,现在where U : int 但你不能用除int之外的任何东西做M的泛型构造。

这可能导致IL生成中的一些真正奇怪的场景,因为CLR具有记录不良的规则,因此它不允许类型参数的“已知为参考类型”的性能在虚拟覆盖。 我为这些方法重新编写了codegen,试图在放弃并返回C#2所做的任何事情之前尝试获得可以编译,传递验证器和jit高效几次的内容。

是否有可能在调用这些方法之一时编写在编译或运行时(即以任何方式)失败的东西?

是的,这在编译时失败了:

public static void CallThem<TA, TB>()
    where TB : class, TA
{
    Register<TA, TB>();         // Fine
    RegisterRestrictive<TA, TB>(); // CS0452
}

没有一对与TInterfaceTImplementation仅匹配其中一个的具体类型,但调用方法的类型参数类型当然可以,而类型参数类型是我们在设计API时需要考虑的类型以及具体类型。

约束不涉及其他约束的推断。

暂无
暂无

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

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