mik*_*ike 6 c# generics inheritance
说问题很难,我希望下面的代码片段能说清楚:
public class DemoClass<TBase> where TBase : class
{
public void DemoMethod<T>(T target) where T : TBase
{
//The following line causes a design-time error: Type argument 'T' does not satisfy the 'Class' constraint for type parameter 'T'.
WeakReference<T> demoRef = new WeakReference<T>(target);
}
}
Run Code Online (Sandbox Code Playgroud)
将WeakReference
需要一个类型,T
即满足class
约束.到目前为止,这么好,但......
为什么编译器无法检测到T
实际发生的情况,因为(实际上)T : TBase : class
?
为什么编译器不能检测到T实际上是这样做的,因为(实际上)T:TBase:class?
因为那根本不是真的.除了Poke在他的回答中指出的,这也是非法的,因为所有值类型都继承自 object
:
var dc = new DemoClass<object>();
dc.DemoMethod(1); //woops, just attempted to create a WeakReference<int>
Run Code Online (Sandbox Code Playgroud)
当涉及到价值类型时,你的推理就会崩溃.做作?是的,但完全合法,所以编译器没有选择,必须考虑您的代码非法.
UPDATE
在上面的代码寻址低于乔恩·哈纳的评论T
是不是真的int
,它object
和1
被隐式装箱,这是绝对不正确的.考虑以下变体DemoMethod
:
public T DemoMethod<T>(T target) where T : TBase
{
return target;
}
Run Code Online (Sandbox Code Playgroud)
以下代码:
var dc = new DemoClass<object>();
var i = dc.DemoMethod(1);
Run Code Online (Sandbox Code Playgroud)
i
是的int
,它不是object
.此外,以下将正确执行:
long i = dc.DemoMethod(1);
Run Code Online (Sandbox Code Playgroud)
这也证明了T
不能盒装,int
因为隐式转换会在运行时失败; 除了类型本身之外,您无法将值类型取消装箱.
当然,你总是可以T
明确地设置,也可以很好地编译:
dc.DemoMethod<int>(1);
Run Code Online (Sandbox Code Playgroud)
让\xe2\x80\x99s 检查文档以了解T : class
实际含义:
\n\n\n\n\n
where T : class
类型参数必须是引用类型;这也适用于任何类、接口、委托或数组类型。
\n
T
不幸的是,如果是一个接口,这就已经满足了。因此,您可以构建一个简单的示例,在其中您可以看到T : class
传递应用不起作用:
public interface ITest { }\npublic struct Test : ITest { }\n
Run Code Online (Sandbox Code Playgroud)\n\n如果您现在创建一个DemoClass<ITest>
,则满足类型约束,因为ITest
这里是 \xe2\x80\x9cclass\xe2\x80\x9d 。但是,当您调用该方法时,尽管继承了,但DemoMethod<Test>
您没有引用类型。T
Test
ITest
一般来说,那些特殊的泛型类型约束不遵循继承规则。这就是为什么它们是单独定义的并且尚未由类型系统建立。它们作为特殊语法存在,因为类型系统无法以其他方式表达约束。
\n 归档时间: |
|
查看次数: |
216 次 |
最近记录: |