带有泛型参数的普通C#类无法编译,没有明显的原因

时间:2011-08-05 13:00:08

标签: c# .net templates generics

我想要一个通用函数,该函数适用于具有TopBottomRightRect只读属性的类型 - 我有很多这样的类在第三方库中。

我写了这个:

internal class MyTemplate<WhatType> {
    internal static void Work( WhatType what )
    {
        int left = what.Left;
    }
};

我期望它能够正常工作--C ++中的等效代码可以正常工作。但是C#对象:

  

错误CS1061:'WhatType'不包含'Left'的定义,并且没有扩展方法'Left'接受类型'WhatType'的第一个参数可以找到(你是否缺少using指令或程序集引用?)

我没理解 - 为什么在我调用之前它会尝试实例化模板?当然,类型WhatType尚不清楚,因此找不到任何属性。

我做错了什么,如何解决?

7 个答案:

答案 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属性的类。