简体   繁体   English

'T' 不包含定义

[英]'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是原始类型,例如intobject怎么办?

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 :例如,如果您有两个实体FooBoo

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:并将FooBoo修改为:

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):假设您希望为添加到数据库的每个实体( FooBoo )设置CreateDateId属性(而不是从服务器默认值):

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM