【问题标题】:Create a Generic list of <T>创建 <T> 的通用列表
【发布时间】:2020-08-12 07:26:11
【问题描述】:

我想创建一个方法来创建一个通用对象列表。可能吗?像这样的:

public class Mtrl 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Code { get; set; }        
    public string Aa { get; set; }
}

public class Trdr 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Code { get; set; }
    public string Address { get; set; }
    public string AFM { get; set; }
    public string Phone01 { get; set; }
    public string Aa { get; set; }
}

然后用一个泛型类来创建我的列表:

public class GenericClass<T>
{        
    public List<T> GetData<T>()
    {
        List<T> myList = new List<T>();
        if (typeof(T) == typeof(Trdr))
        {
            myList.Add(new Trdr());//Error 1: cannot convert from Trdr to 'T'   
        }
        if (typeof(T) == typeof(Mtrl))//Error 2: cannot convert from Mtrl to 'T'    
        {
            myList.Add(new Mtrl());
        }
        return myList;
    }
}

我的错。我将尝试澄清更多。 Trdr、Mtrl 等类将具有许多不同的属性。 Getdata 方法将通过 json 从 Web 服务获取数据,我想创建一个对象列表并返回它 像这样的:

public List<T> GetData<T>()
        {
            List<T> myList = new List<T>();
            if (typeof(T) == typeof(Trdr))
            {
                for (int i = 0; i < 100; i++)//fetch data from web api in json format
                {
                    Trdr NewObj = new Trdr();
                    NewObj.Aa = "...";
                    NewObj.AFM = "...";

                    myList.Add(NewObj);
                }
            }
            if (typeof(T) == typeof(Mtrl))
            {
                for (int i = 0; i < 100; i++)
                {
                    Mtrl NewObj = new Mtrl();
                    NewObj.Aa = "...";
                    NewObj.Name = "name ...";

                    myList.Add(NewObj);
                }
            }
            return myList;
        }
    }

【问题讨论】:

  • 但是List&lt;T&gt; 已经是通用的了?你真的不需要这样做吗?
  • 虽然您可以只添加一个演员表,但有一个安全的机制可以做到这一点:添加new 约束public List&lt;T&gt; GetData&lt;T&gt;() where T : new() { /* code */ list.Add(new T()); }。但是我想知道你在这里想要做什么,你想达到什么目标?
  • 为什么不能为此创建 2 个方法?或者,您可以通过反射调用List&lt;T&gt;.Add,尽管我认为这不应该是 the 解决方案。或者您可以在两个类中添加interface,并在方法签名中使用where T : IMyInterface
  • 一个只适用于两种特定类型的 generic 方法并不是真正的 generic,是吗?除非您的两个类都具有相同的基类或接口,否则您不应该在这里使用泛型。除此之外,您似乎只添加了一个元素,使 list 变得毫无意义。或者这只是演示?
  • public List&lt;T&gt; GetData&lt;T&gt;() Where T : new { return new List&lt;T&gt;(){new T()}; ?虽然这完全是多余的

标签: c# list generics


【解决方案1】:

我建议提取一个接口(甚至是一个基类):

 //TODO: Since you have more than 2 classes, please check the common interface 
 public interface Idr {
   string Id   { get; set; }
   string Name { get; set; }
   string Code { get; set; }        
   string Aa   { get; set; }
 }

所有感兴趣的类都实现它:

public class Mtrl : Idr
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Code { get; set; }        
    public string Aa { get; set; }
}

public class Trdr : Idr 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Code { get; set; }
    public string Aa { get; set; }

    public string Address { get; set; }
    public string AFM { get; set; }
    public string Phone01 { get; set; }
}

现在你可以使用List&lt;Idr&gt;收藏;我们希望实现Idr 的类(T)也有一个无参数构造函数(new()):

public class GenericClass<T> where T : Idr, new()
{        
    public List<T> GetData()
    {
        List<T> myList = new List<T>() {
          new T();
        };

        return myList;
    }
}

【讨论】:

    【解决方案2】:

    听起来您正在尝试创建一个包含一些初始数据的新列表,并且您需要为许多不同的类型执行此操作T

    如果MtrlTrdr 没有任何共同点并且处理方式完全不同,请考虑简单地使用不同的方法来获取每种类型的列表:

    GetDataMtrl(){
        var result = new List<Mtrl>();
        result.Add(new Mtrl());
        return result;
    } // etc
    

    否则你需要的是Type Constraints of Generic Parameters,它可以告诉编译器更多关于T是什么。或者更确切地说,T 的不同值必须有什么共同点。例如你可以做

        public List<T> GetData<T>() where T : new()
        {
            List<T> myList = new List<T>();
    
            myList.Add(new T());
    
            return myList;
        }
    

    要说T 必须可以做到new T()。然后你可以说GetData&lt;Trdr&gt;() 来获得一个包含单个空Trdr 的列表,就像你的代码可能试图做的那样。

    也许您需要在数据中设置一些默认值。我注意到这些类有很多共同的变量。那么你可以考虑使用继承来指定这个共性:

    public class Mtrl 
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Code { get; set; }        
        public string Aa { get; set; }
    }
    
    public class Trdr : Mtrl
    {
        public string Address { get; set; }
        public string AFM { get; set; }
        public string Phone01 { get; set; }
    }
    

    然后编写通用代码,其中TMtrl 类型或其后代类:

        public List<T> GetData<T>() where T : Mtrl
        {
            List<T> myList = new List<T>();
            T MtrlOrTrdr = new T();
            MtrlOrTrdr.Id = "my-new-id-";
    
            myList.Add(MtrlOrTrdr);
    
            return myList;
        }
    

    【讨论】:

      猜你喜欢
      • 2014-02-08
      • 1970-01-01
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 2018-08-25
      • 1970-01-01
      • 2010-10-14
      • 2013-07-24
      相关资源
      最近更新 更多