【问题标题】:Is there a syntactic sugar C# property syntax to instantiate generic collections?是否有语法糖 C# 属性语法来实例化泛型集合?
【发布时间】:2023-03-09 10:08:01
【问题描述】:

以下程序将失败,因为 Contracts 未实例化。

当然我可以在我的构造函数中实例化它,但是如果我有几十个属性和/或多个构造函数,我必须跟踪哪些被实例化了,等等。

当然,我可以使用完整的获取和设置以及私有字段变量等为这些属性创建大块。但这也会变得混乱。

难道没有办法用漂亮的 C# 属性语法自动实例化这些集合吗?

using System;
using System.Collections.Generic;

namespace TestProperty232
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer = new Customer();
            customer.FirstName = "Jim";
            customer.LastName = "Smith";

            Contract contract = new Contract();
            contract.Title = "First Contract";

            customer.Contracts.Add(contract);

            Console.ReadLine();
        }
    }

    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public List<Contract> Contracts { get; set; }

        public Customer()
        {
            //Contracts = new List<Contract>();
        }
    }

    public class Contract
    {
        public string Title { get; set; }
    }
}

【问题讨论】:

    标签: c# syntax properties


    【解决方案1】:

    没有这样的语法糖,但我想指出几点:

    • Collection properties should be read-only 无论如何。
    • 如果您在单一类型中有很多此类属性,则强烈表明您违反了单一职责原则
    • 如果您有多个构造函数,您应该始终非常小心,只有一个构造函数可以完成实际工作,并且所有其他构造函数都委托给该构造函数。或者,您可以将所有构造函数的工作委托给私有 Initialize 方法。

    【讨论】:

    • 您使用的是哪个版本的 C#?
    • 重新收集属性 - 除了XmlSerializer 的烦人琐事,但理论上同意。
    • 在当前版本的C#中,如果我理解这个问题,这个答案是错误的。有语法糖(根据我的回答)。
    • @Joe:如果我正确理解了 OP,他并不是在询问类型初始化器,而是在询问是否有某种速记,例如 Auto-Properties,它允许您以声明方式指定 List 属性存在。这应该确保在创建对象时 List 实例可用(即不为空)。至少在 C# 3 中没有这样的东西,我不相信在 C# 4 中也有。
    • @BillW:听起来你刚刚描述了延迟初始化。当然,在某些情况下这样做是合适的,但是在这个 cmets 字段中不可能将它们全部列出。不过,这从来都不是我的默认方法-我宁愿尽快检查不变量...但是,您的问题听起来像是“正确” Stack Overflow 问题的不错选择:)
    【解决方案2】:

    不,没有糖。在您的无参数构造函数中实例化它们并在那里重定向所有其他构造函数,以便它始终执行。

    class MyClass
    {
        //Many properties
    
        public MyClass()
        {
            //Initialize here
        }
    
        public MyClass(string str) : this()
        {
            //do other stuff here
        }
    }
    

    【讨论】:

      【解决方案3】:

      长答案:这是怎么回事?

      using System.Collections.Generic;
      
      namespace proto
      {
          public class Customer
          {
              public string FirstName { get; set; }
      
              public string LastName { get; set; }
      
          }
      
          public class Contract
          {
              public List<Customer> Customers { get; set; }
      
              public string Title { get; set; }
          }
      
          public class ContractDemo
          {
              public Contract CreateDemoContract()
              {
                  Contract newContract = new Contract
                  {
                      Title = "Contract Title", 
                      Customers = new List<Customer>
                      {
                          new Customer
                          {
                              FirstName = "First Name",
                              LastName = "Last Name"
                          },
                          new Customer
                          {
                              FirstName = "Other",
                              LastName = "Customer"
                          }
                      }
                  };
      
                  return newContract;
              }
      
          }
      }
      

      【讨论】:

        【解决方案4】:

        含糖还是柠檬:由您决定:(VS 2010 beta 2,FrameWork 4)

            Customer customer = new Customer
            {
                FirstName = "Jim", 
                LastName = "Smith", 
                Contracts = new List<Contract> { new Contract { Title ="First Contract" } }
            };
        

        适用于您现有的类定义,但阅读起来感觉很尴尬?

        最好的,

        【讨论】:

          【解决方案5】:

          简短的回答是

          【讨论】:

          • 长答案是Nooooooooooooooooooooooooooooooo
          • 长答案是 looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong ;)
          【解决方案6】:

          不确定你真正在寻找什么,但你可以像这样整理一下......

          using System;
          using System.Collections.Generic;
          
          namespace TestProperty232
          {
              class Program
              {
                  static void Main(string[] args)
                  {
                      Customer customer = new Customer() { 
                          FirstName = "Jim",
                          LastName = "Smith"
                      };
          
                      Contract contract = new Contract() { 
                          Title = "First Contract"
                      };
          
                      customer.Contracts = new List<Contract>() { contract };
          
                      Console.ReadLine();
                  }
              }
          
              public class Customer
              {
                  public string FirstName { get; set; }
                  public string LastName { get; set; }
                  public List<Contract> Contracts { get; set; }
          
                  public Customer()
                  {
                      //Contracts = new List<Contract>();
                  }
              }
          
              public class Contract
              {
                  public string Title { get; set; }
              }
          }
          

          【讨论】:

            【解决方案7】:

            您可以让合同不是自动属性:

            private List<Contract> _contracts;
            public List<Contract> Contracts
            {
                get
                {
                    if (_contracts == null)
                    {
                        _contracts = new List<Contract>();
                    }
                    return _contracts;
                }
                set
                {
                    if (!_contracts.Equals(value))
                    {
                        _contracts = value;
                    }
                }
            }
            

            这将使您不必显式实例化合同。

            【讨论】:

            • 你可以使用一些语法糖来缩短它:get { return _contracts ?? (_contracts = new List&lt;Contract&gt;()); }
            • @Joel 谢谢!十五分钟前我只是在尝试这种技术(使用空合并运算符),并且对为什么我收到一条错误消息感到疯狂:“赋值的左侧必须是变量、属性或索引器” :我未能将私有支持字段的初始化(在 ?? 运算符的右侧)_contracts 括在括号中 :)
            猜你喜欢
            • 2016-01-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-04-25
            • 2021-08-16
            • 1970-01-01
            • 2020-02-14
            • 2011-09-01
            相关资源
            最近更新 更多