我们如何看待在C#中将属性用作对象初始值设定项?

时间:2020-03-06 14:19:28  来源:igfitidea点击:

我想知道人们如何在C#中使用属性作为对象初始化器。由于某种原因,这似乎打破了构造函数的基本原理。

一个例子...

public class Person
{
    string firstName;
    string lastName;

    public string FirstName
    {
      get { return firstName; }
      set { firstName = value; }
    }

    public string LastName
    {
      get { return lastName; }
      set { lastName= value; }
    }
}

然后用.....进行对象初始化

Person p = new Person{ FirstName = "Joe", LastName = "Smith" };
Person p = new Person{ FirstName = "Joe" };

解决方案

恕我直言,它的甜蜜。大多数对象是使用默认构造函数进行更新的,并且在运行之前必须设置一些属性。因此,对象初始值设定项使针对那里的大多数对象进行编码变得更加容易。

我们在这里看到的是编译器提供的一些语法糖。实际情况下,它实际上是这样的:

人p =新人(名字="乔",姓="史密斯");

Person _p = new Person();
_p.FirstName = "Joe";
_p.LastName = "Smith";
Person p = _p;

因此,恕我直言,我们并没有真正破坏任何构造函数的基础,而是使用了不错的语言构件来简化可读性和可维护性。

我认为总体而言,它很有用,尤其是与自动属性一起使用时。
当属性所做的事情超出获取/设置的范围时,可能会造成混淆。
希望这将导致更多方法,并减少对属性的滥用。

对于从语言集成查询(linq)返回的投影类,这也是非常必要的

var qry = from something in listofsomething
          select new {
                        Firstname = something.FirstName,
                        Lastname = something.Surname
                      }

对象初始化程序绝不会替代构造函数。构造函数定义了创建类实例时必须遵守的协定。

语言中对象初始化程序的主要动机是支持匿名类型。

var v = new { Foo = 1, Bar = "Hi" };
Console.WriteLine(v.Bar);

对象初始化程序有助于减少编码复杂性,因为我们无需创建六个不同的构造函数即可为属性提供初始值。在我的书中,减少冗余代码的任何事情都是积极的。

我相信将该功能添加到语言的主要原因是为了支持LINQ的匿名类型。

我在代码审查中建议的Nescio想法得到了补充,它积极地追捕了财产访问者中昂贵的透明操作,例如DB往返。

由于我们已经在使用新的Csyntax,因此不妨同时使用自动属性,只是为了使代码更加优美:

而不是这样:

string firstName;

public string FirstName
{
  get { return firstName; }
  set { firstName = value; }
}

用这个:

public string FirstName { get; set; }

构造函数只应真正具有构造对象所需的参数。对象初始化程序只是将值分配给属性的便捷方法。我尽可能使用对象初始化程序,因为我认为这是一种整齐的语法。

如果要强制使用构造函数,可以将对象的默认无参数构造函数设置为private,而仅将一些强制的构造函数保留为public:

public class SomeObject
{
    private SomeObject()
    {}

    public SomeObject(string someString) //enforced constructor
    {}

    public string MyProperty { get; set; }
 }

使用上面的定义,这将引发错误:

var myObject = new SomeObject { MyProperty = "foo" } //no method accepts zero arguments for constructor

当然,并非所有情况都可以做到这一点。例如,序列化要求我们具有一个非私有的默认构造函数。

不是我们最初的问题,但仍然...

课程声明可以写成:

public class Person
{
    public string FirstName { get; set; }
    public string LastName {get; set; }
}

如果是我的代码,则可能会有一个名称为Name的对象,其字段为First和Last。

我对他们不满意。我认为它们没有在构造函数中占有一席之地,否则MS应该找回并重构它们,以允许我们以私密方式使用它们。如果我构造一个对象,我想传递一些PRIVATE数据。我希望它一次从外界设置,仅此而已。使用对象初始化器,我们可以允许更改传入构造函数的值。

也许将来他们会改变这一点。