【问题标题】:Unable to create property for a generic class无法为泛型类创建属性
【发布时间】:2012-01-04 23:48:36
【问题描述】:
public class Address
{
    public string streetno;
    public string streetname;
    public string suburb;
    public string postcode;
    public Country country;
}
public class Country
{
    public string name;
}

public class Person<A>
    where A : new()
{
    public A address;

    public Person()
    {
        address.country = new Country();
    }
}

当我编译上面的代码时,我得到以下错误: 错误 CS1061:“A”不包含“国家”的定义,并且找不到接受“A”类型的第一个参数的扩展方法“国家”(您是否缺少 using 指令或程序集引用?)

关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: c# generics


    【解决方案1】:

    嗯,首先您需要了解错误。如果我们这样写,你会期望发生什么:

    Person<string> x = new Person<string>();
    

    这将创建一个具有address 类型为string 的字段的对象。现在string 没有country 属性,所以没有意义。

    我不清楚您为什么希望它从一开始就具有通用性,但您可以添加一个额外的约束,以便 A 必须是 Address 或派生类(大致说话):

    public class Person<A> where A : Address, new()
    

    现在您将获得NullReferenceException - 因为您没有创建地址的新实例...您的构造函数需要更改为:

    public Person()
    {
        address = new A();
        address.country = new Country();
    }
    

    或者,为了获得更大的灵活性,您可能希望创建一个IAddress 接口 并用它而不是类来表达约束......但这取决于你。如果不详细说明您正在做什么,很难推荐具体的行动方案。

    【讨论】:

      【解决方案2】:

      您不能像这样引用泛型类型的特定属性,除非您已经给出了具有这些属性的泛型类型约束。例如,如果你声明你的类:

      public class Person<T> where T : Address, new()
      {
          public T address;
      
          public Person()
          {
              this.address.Country = new Country();
          }
      }
      

      当然,如果你只有那个地址类,那可能会破坏目的。这是一个泛型类,其中泛型类型参数是地址,这似乎很奇怪。另一种方法是使用动态关键字:

      public class Person
      {
          public dynamic address;
      
          public Person()
          {
              this.address.Country = new Country();
          }
      }
      

      【讨论】:

        【解决方案3】:

        您必须将您的类型限制为支持 country 属性的类型。由于直接使用 Address 类毫无意义,请考虑使用某种类型的基类 /interface。

        public interface IAddress
        {
            public string streetno { get; set; }
            public string streetname { get; set; }
            public string suburb { get; set; }
            public string postcode { get; set; }
            public Country country { get; set; }
        }
        
        public class Person<A>
            where A : IAddress
        {
            public A address;
        
            public Person()
            {
                address.country = new Country();
            }
        }
        

        【讨论】:

          【解决方案4】:

          我可能提交了一个不好的例子。这更接近我所拥有的:

          namespace SomeNamespace
          {
              public class SomeHeader
              {
          
              }
          
              public class SomeParamaters
              {
          
              }
          
              public class SomeRequest
              {
                  public SomeHeader Header;
                  public SomeParamaters Parameters;
              }
          }
          
          using SomeNamespace;
          
          namespace MyNamespace
          {
          
              public class Worker<A>
                  where A : new()
              {
                  public A req;
          
                  public void DoSomeMeaningfulWork()
                  {
                      req.Header = new SomeHeader();
                      req.Parameters = new SomeParamaters();
                  }
              }
          }
          

          请注意类SomeXXX继承自对象并实现System.ComponentModel.INotifyPropertyChanged

          我选择泛型的原因是有很多请求、标头、参数、响应、数据、错误组。基本上,每种类型的请求都定义了一个系列。

          工人类 - 在写完 3 之后,请求、标头、参数、响应、数据、错误完全相同。

          我不知道 dynamic 关键字 - 但它确实听起来像我所追求的,因为我确切知道需要调用的属性 - 它们完全相同并且属于相同类型。

          但是,我的问题是,我使用的是 .net 3.5 和 vs 2008

          我已经考虑过接口和约束,但它们似乎不适用于我当前面临的问题。

          【讨论】:

          • 鉴于 DoSomeMeaningfulWork 中的代码,我看不出接口无法满足您的要求的地方。只需将通用属性放在该界面中即可。
          猜你喜欢
          • 2013-01-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-01
          相关资源
          最近更新 更多