带有泛型参数的普通c#类将无缘无故地无法编译
本文关键字:无缘无故 编译 泛型 参数 | 更新日期: 2023-09-27 18:04:49
我想要一个泛型函数,可以与具有Top
, Bottom
, Right
和Rect
只读属性的类型一起工作-我在第三方库中有很多这样的类。
我写的是:
internal class MyTemplate<WhatType> {
internal static void Work( WhatType what )
{
int left = what.Left;
}
};
,我希望它能工作-在c++中等效的代码也可以工作。但是c#对象:
错误CS1061: 'WhatType'不包含'Left'的定义,并且没有扩展方法'Left'接受类型'WhatType'的第一个参数可以找到(您是否缺少using指令或程序集引用?)
我不明白-为什么它会在我调用它之前尝试实例化模板?当然,类型WhatType
还不知道,所以没有找到任何属性。
我做错了什么,我如何解决这个问题?
c#泛型不是模板;它们是在运行时提供的,而不是由编译器提供的。因此,没有鸭子打字。两个选择:
- 使用
where WhatType : ISomeInterface
约束,其中ISomeInterface
有Left {get;}
- 使用
dynamic
(提供duck-typing)
。
internal class MyTemplate<WhatType> where WhatType : ISomeInterface {
internal static void Work( WhatType what )
{
int left = what.Left;
}
};
interface ISomeInterface {
int Left { get; }
}
或:
internal class MyTemplate<WhatType> {
internal static void Work( WhatType what )
{
int left = ((dynamic)what).Left;
}
};
c#泛型看起来类似于c++模板,但实际上它们有很大的不同。c#泛型是强类型的,所以你不能调用非静态已知的成员。
为了能够在WhatType
类型的对象上调用Left
,您必须使用泛型约束指定WhatType
实现接口或继承定义Left
的类。例如:
interface IHasPosition
{
int Left { get; }
int Top { get; }
}
internal class MyTemplate<WhatType> where WhatType : IHasPosition
{
internal static void Work( WhatType what )
{
int left = what.Left;
}
};
您可以这样指定类型:
internal class MyTemplate<WhatType> where WhatType : LeftInterface
那么你可以使用.Left
调用。
LeftInterface
可能看起来像这样:
public interface LeftInterface
{
int Left {get; set;}
}
泛型用于类型安全。现在,没有任何关于WhatType
的额外信息,编译器如何知道传入的实例what
将具有Left
属性?
你需要这样的东西
public interface IFoo
{
int Left {get;}
}
和
internal class MyTemplate<WhatType> where WhatType : IFoo {
必须在where子句中指定支持。left的基类,或者必须将what强制转换为支持。left -property的类型:
internal class MyTemplate<WhatType> where WhatType : YourBaseClassWithLeftProperty
或
internal class MyTemplate<WhatType> {
internal static void Work( WhatType what ) {
YourBaseClassWithLeftProperty yourInstance=what as YourBaseClassWithLeftProperty;
if(null != yourInstance){
int left = yourInstance.Left;
}
}
...
嘿,男孩,你只是需要这个:
强制在c#中实现泛型接口
这样你就可以假设你的WhatType
实例将有Left, Bottom等等…
您没有为WhatType
类型指定任何条件,因此它将接受任何类型,并且只知道每种类型所知道的,即只知道Object
类中定义的内容。
如果你想在类型中使用其他任何东西,你必须指定它包含什么,你可以通过指定它必须实现一个接口或继承一个类来实现:
internal class MyTemplate<WhatType> where WhatType : BaseType {
其中BaseType
可能是定义了Left
属性的接口或类