[英]'T' does not contain a definition
Is it possible to do the following (If so I can't seem to get it working.. forgoing constraints for the moment)...是否可以执行以下操作(如果是这样,我似乎无法使其正常工作......暂时放弃限制)......
If the type (because it's ommitted) is inferred, what's the problem?如果类型(因为它被省略)被推断出来,有什么问题?
private void GetGenericTableContent<T>(ref StringBuilder outputTableContent, T item)
{
outputTableContent.Append("<td>" + item.SpreadsheetLineNumbers + "</td>");
}
// 'item' is either DuplicateSpreadsheetRowModel class or SpreadsheetRowModel class
With the above code I get the following error:使用上面的代码,我收到以下错误:
'T' does not contain a definition for 'SpreadsheetLineNumbers' and no extension method 'SpreadsheetLineNumbers' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?) “T”不包含“SpreadsheetLineNumbers”的定义,并且找不到接受“T”类型的第一个参数的扩展方法“SpreadsheetLineNumbers”(您是否缺少 using 指令或程序集引用?)
No, Generic types must be known at compile time.不,在编译时必须知道泛型类型。 Think about it for a minute, how could compiler know that it is guaranteed that type T
has property SpreadsheetLineNumbers
?想一想,编译器怎么知道可以保证类型T
具有属性SpreadsheetLineNumbers
? What if T
is of primitive type such as int
or object
?如果T
是原始类型,例如int
或object
怎么办?
What prevents us from calling the method like this: GetGenericTableContent(ref _, 999)
with T as int here ?是什么阻止我们调用这样的方法: GetGenericTableContent(ref _, 999)
with T as int here ?
To fix it you could first add an interface that contains the property :要修复它,您可以先添加一个包含属性的接口:
public interface MyInterface
{
string SpreadsheetLineNumbers { get; set; }
}
And let your class inherit from this interface:让你的类继承这个接口:
public class MyClass : MyInterface
{
public string SpreadsheetLineNumbers { get; set; }
}
Then we use generic type constraints to let compiler know that the type T
derives from this interface and therefore it has to contain and implement all its members:然后我们使用泛型类型约束让编译器知道类型T
派生自这个接口,因此它必须包含并实现其所有成员:
private void GetGenericTableContent<T>(ref StringBuilder outputTableContent, T item)
where T : IMyInterface // now compiler knows that type T has implemented SpreadsheetLineNumbers
{
outputTableContent.Append("<td>" + item.SpreadsheetLineNumbers + "</td>");
}
If you can't get make an interface for your type (or a common one between several types):如果您无法为您的类型(或几种类型之间的通用接口)创建接口:
private void GetGenericTableContant<T>(ref StringBuilder outputTableContent, T item, Func<T, string> lineNumberAccessor)
{
outputTableContent.Append("<td>" + lineNumberAccessor(item) + "</td>");
}
Usage:用法:
GetGenericTableContent(ref outputTableContent, item, x => x.SpreadsheetLineNumbers);
(Or you could just pass the SpreadSheetLineNumbers property if you don't really need the item reference in your method: void GetGenericTableContant<T>(ref StringBuilder outputTableContent, string lineNumbers)
) (或者,如果您真的不需要方法中的项目引用,您可以只传递 SpreadSheetLineNumbers 属性: void GetGenericTableContant<T>(ref StringBuilder outputTableContent, string lineNumbers)
)
Actually it is possible if you know for sure that the generic T has the exact property, using the where (generic type constraint) for a specified class with where T : MyClass
.实际上,如果您确定泛型 T 具有确切的属性,则可以使用where (泛型类型约束)为指定类使用where T : MyClass
。
For instance, if you have two entities Foo
and Boo
:例如,如果您有两个实体Foo
和Boo
:
class Foo
{
public Guid Id {get; set;}
public DateTime CreateDate {get; set;}
public int FooProp {get; set;}
}
class Boo
{
public Guid Id {get; set;}
public DateTime CreateDate {get; set;}
public int BooProp {get; set;}
}
With a little refactor we can create a BaseClass
that will hold the common properties:通过一些重构,我们可以创建一个BaseClass
来保存公共属性:
class BaseModel
{
public Guid Id {get; set;}
public DateTime CreateDate {get; set;}
}
And modify Foo
and Boo
to be:并将Foo
和Boo
修改为:
class Boo : BaseModel
{
public int BooProp {get; set;}
}
class Foo : BaseModel
{
public int FooProp {get; set;}
}
And If you have a generic service with the constraint type of where T : BaseModel
the compiler will allow you to get or set the BaseModel
's properties.如果您有一个约束类型为where T : BaseModel
的通用服务,编译器将允许您获取或设置BaseModel
的属性。
Lets say that you want that for every entity ( Foo
or Boo
) added to DB you will want to set the CreateDate
and Id
properties from code (and not from server default value):假设您希望为添加到数据库的每个实体( Foo
或Boo
)设置CreateDate
和Id
属性(而不是从服务器默认值):
public interface IGenericService<T>
{
void Insert(T obj);
}
public class GenericService<T> : IGenericService<T> where T : BaseModel
{
public void Insert(T obj)
{
obj.Id = Guid.NewGuid();
obj.CreateDate = DateTime.UtcNow;
this._repository.Insert(obj);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.