2012-07-23 25 views
5

我想创建一个泛型类的定义:T不包含RowKey

public class ClassName<T> 
{ 
    public T AccessEntity(string id) 
    { 
     return (from e in ServiceContext.CreateQuery<T>(TableName) 
       where e.RowKey == id // error here! 
       select e).FirstOrDefault(); 
    } 
} 

在这段代码中我得到错误:

T不包含RowKey定义

但在运行时将取代T的参数具有RowKey的定义。也许因为编译器在编译时没有得到T中RowKey的定义,这就是为什么我得到这个错误。任何人都可以告诉我如何解决这个问题?

+0

参考作为注释 - 我upvoted正确答案之一:编译不在乎T将是什么版本。它关心在编译时它知道些什么,这意味着你可以创建ClassName ,并且Dumbo没有RowKey - >错误。 Adda约束;) – TomTom 2012-07-23 14:53:29

+0

Pro说明了TomTom的观点:在c#中,你可以在运行时编写一个*类型,并且调用新类型的泛型类型 - 只要满足约束条件,它就可以工作。这与C++模板非常不同。 – 2012-07-23 15:08:27

回答

11

要做到这一点,你需要一个接口约束:

interface IHazRowKey { 
    string RowKey { get; } 
} 

,并指定此限制:

public class classname<T> where T : IHazRowKey {...} 

而且在每一个实现指定: IHazRowKey

public class Foo : IHazRowKey {....} 

的现有的RowKey会员应该匹配它(假设我t是一个属性,而不是一个字段),所以你不需要添加任何其他额外的代码。如果它实际上是一个字段(它不应该,IMO),则:

public class Foo : IHazRowKey { 
    string HazRowKey.RowKey { get { return this.RowKey; } } 
    ... 
} 
+3

不应该是ICanHazRowKey吗? :) – 2012-07-23 14:53:25

+0

谢谢你的回答,但是我作为一个泛型类实现的类已经从另一个类驱动出来,抱歉没有提到这个问题。意思是这样的:public class ClassName :Base – 2012-07-23 14:57:54

+2

@Tom不会改变任何东西;你被允许多接口继承和单类继承, – 2012-07-23 15:06:43

1
class YourClass // or extract an interface 
{ 
    public string RowKey { get; set; } 
} 

class YourGeneric<T> where T : YourClass 
{ 
    // now T is strongly-typed class containing the property requested 
} 
3

您需要定义constraint来解决这个问题:

public interface IHasRowKey 
{ 
    string RowKey {get;} 
} 

public class classname<T> where T : IHasRowKey 
{ 

} 
8

有C++模板和C#泛型之间的主要区别:不要紧,你通过什么类来实例化通用的,如果编译器在编译泛型类或方法时不知道T上的方法,它会给你一个错误。这是因为C#需要能够将泛型代码与实例化地点分开编译(请记住,C#中没有头文件)。

您可以定义一个接口,并将其限制为T以便在泛型中使用属性和方法。将RowKey添加到您的界面,并将where T : myinterface添加到您的通用声明中。

0

我的情况下不能使用界面包含RowKey,因为我有一个有不同的属性和方法两大类。我不能将它们合并,并将这些属性和方法放入一个包装接口或类中,导致它失去了使用泛型类的目的。我的解决方案是使用Generic类的反射。例如: -

public class ClassName<T> { 
    private T _genericType; 
    public ClassName(T t) { 
     _genericType = t; 
    } 

    public void UseGenericType() { 
     // Code below allows you to get RowKey property from your generic 
     // class type param T, cause you can't directly call _genericType.RowKey 
     PropertyInfo rowKeyProp = _genericType.GetType().GetProperty("RowKey"); 
     if(rowKeyProp != null) { // if T has RowKey property, my case different T has different properties and methods 
      string rowKey = rowKeyProp.GetValue(_genericType).ToString(); 
      // Set RowKey property to new value 
      rowKeyProp.setValue(_genericType, "new row key"); 
     } 
    } 
} 

这里是一个的PropertyInfo类http://msdn.microsoft.com/en-us/library/System.Reflection.PropertyInfo_methods(v=vs.110).aspx