12

C#有人可以建议我在编写构造函数时采取什么方法吗?

在其他语言中,例如C++,一切都很好 - 您通常不会使内部字段可见并为它们提供 getter / setter。

这意味着,您可以为您的类提供构造函数,它们初始化所有/部分本地成员并感到高兴。


C#, 但是, has properties, 它允许我们编写如下内容:

Class x = new Class { Field1 = new Field1 ...., Field2 = new Field2 }

这允许链接对象构造,并且正如我所假设的那样,可以删除许多构造函数,如果我们没有properties.

正如我所假设的,将它与属性的默认值结合起来,我们可以完全摆脱非专业构造函数,它们实际上做了一些工作。

现在 - 可以删除多余的构造函数并允许通过字段初始化来构造对象吗?

这种方法的缺点是什么?有人可以给出关于结合使用字段和构造函数的一般建议rules of thumb吗?

谢谢你。

4

9 回答 9

16

我自己的经验法则很简单:如果完全构造对象需要某些东西,它应该是一个 ctor 参数。

一个很好的例子是 StreamReader 或 BinaryReader 等 Stream 帮助器对象之一。它们不能在没有关联的 Stream 对象的情况下运行,因此必须在构造函数中指定。

于 2011-03-30T12:49:44.973 回答
6

在我看来,拥有你所说的冗余构造函数并没有错。如果定义构造函数对您来说足够有意义,那可能是因为确实需要这样做。

于 2011-03-30T12:48:41.870 回答
4

构造函数可用于强制消费者向类提供值。

我的经验法则是字段用于可选数据,而构造函数可用于强制所需数据。

不过,这个问题是一种错误的二分法。C++ 的行为方式与 C# 相同 - “字段”(实际上是属性 - 字段是类级别的变量)通常用作设置内部值的 getter/setter,new允许您设置字段的语法只是

Class x = new Class();
x.Field1 = new Field1();
x.Field2 = new Field2();
于 2011-03-30T12:49:30.553 回答
2

最佳实践是创建一个处于可用状态的对象;尽量限制对财产设置者的依赖。

它减少了您创建不完整对象并导致代码不那么脆弱的机会。

于 2011-03-30T12:49:59.297 回答
2

您发布的代码使用了所谓的 Object Initializers,它们实际上只是最近引入的语法糖。使用对象初始化器只是调用构造函数设置属性的一种简写方式。您应该继续在 C# 中使用构造函数,就像在其他语言中使用构造函数一样——一般规则是,如果一个类需要一个对象或值才能正确初始化,则该参数应该通过构造函数传递。如果不需要该值,则将其设为可设置属性是合理的。

一般来说,我尽可能避免使用设置器有很多很多情况下是不可能的)。

于 2011-03-30T12:50:41.387 回答
1

公共无参数构造后跟属性初始化的方法在 XAML 中很流行(需要?),很多 WPF 玩具都这样做。

您面临的唯一问题是部分初始化的对象,但是您可以在尝试使用这些字段之前简单地验证对象状态。

就个人而言,我在构造函数中创建了关键值参数,我从对象的副本和一系列可选参数中创建了复制构造函数,并且我还没有创建需要 XAML 使用的东西。

于 2011-03-30T12:51:35.163 回答
1

对象初始化器语法只是一个语法糖。即使在 C# 1 中,您也可以编写

Class c = new Class();
c.Property1 = value1;
c.Property2 = value2;
c.Property3 = value3;
....

C# 3 基本上将语法缩短为:

Class c = new Class 
{
   Property1 = value1, 
   Property2 = value2, 
   Property3 = value3
   ....
}

构造函数的重点不是仅仅设置字段,构造函数应该根据参数在逻辑上构造对象,这样当构造函数返回时,你得到的是一个可以使用的对象。

于 2011-03-30T12:54:27.327 回答
0

可以吗?嗯,这取决于...

为了使用对象初始化器,您需要向所有字段公开公共设置器,您可能不希望这样做。如果您愿意公开它们,那么我会说继续并删除构造函数。然而,仅仅因为你可以做某事并不意味着你应该。如果您发现所有字段都是可公开设置的,我会说删除构造函数应该是您应该做的事情,不要让字段可设置只是为了让您删除构造函数。

于 2011-03-30T12:51:58.140 回答
0

我怀疑您在这里指的是域对象,但是在服务的情况下,通过构造函数注入服务的依赖项会使服务更加自我记录,而不是“更新”您的依赖项。此外,这使您可以更轻松地使用依赖注入容器。

于 2011-03-30T12:58:08.073 回答