我想要一个通用函数,该函数适用于具有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
尚不清楚,因此找不到任何属性。
我做错了什么,如何解决?
答案 0 :(得分:8)
C#泛型不是模板;它们是在运行时提供的,而不是由编译魔术提供的因此,没有鸭子打字。两个选项:
where WhatType : ISomeInterface
约束,其中ISomeInterface
具有Left {get;}
dynamic
(提供鸭子打字)即
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;
}
};
答案 1 :(得分:4)
您可以指定如下类型:
internal class MyTemplate<WhatType> where WhatType : LeftInterface
然后您可以使用.Left
来电。
LeftInterface
可能如下所示:
public interface LeftInterface
{
int Left {get; set;}
}
答案 2 :(得分:4)
C#泛型看起来与C ++模板类似,但它们实际上是完全不同的。 C#泛型是强类型的,因此您无法调用非静态的成员。
为了能够在Left
类型的对象上调用WhatType
,您必须指定WhatType
实现接口或从定义{{1}的类继承},使用通用约束。例如:
Left
答案 3 :(得分:2)
泛型用于类型安全。现在没有关于WhatType
的任何其他信息,编译器如何知道传入的实例what
将具有属性Left
?
你需要这样的东西
public interface IFoo
{
int Left {get;}
}
和
internal class MyTemplate<WhatType> where WhatType : IFoo {
答案 4 :(得分:1)
您必须在where子句中指定支持.Left的基类,或者必须将类型转换为支持.Left属性的类型:
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;
}
}
...
答案 5 :(得分:0)
嘿,小伙子,你只需要这个:
Force generic interface implementation in C#
这样您可以稍后假设您的WhatType
实例将具有Left,Bottom等等......
答案 6 :(得分:0)
您没有为WhatType
类型指定任何条件,因此它将接受任何类型,并且只知道每个类型知道什么,即只知道Object
类中定义的内容。
如果要使用该类型中的任何其他内容,则必须指定它包含的内容,通过指定它必须实现接口或从类继承来执行:
internal class MyTemplate<WhatType> where WhatType : BaseType {
BaseType
可以是接口,也可以是定义Left
属性的类。