C#将构造函数参数传递给私有成员的目的是什么?

时间:2015-04-04 06:54:23

标签: c#

人们总是定义一个私有成员,然后将构造函数参数值传递给它,比如设计A.但我无法理解这样做的好处,因为私有成员没有得到副本(我的意思是深度克隆)那么为什么不选择设计B呢?

设计A:

public class ClassA
{
    public int num {get;set;}
}

public class ClassB 
{

    private ClassA a ;

    public ClassB(ClassA _a) {
        a = _a;
    }
}

设计B:

public class ClassA
{
    public int num {get;set;}
}

public class ClassB 
{
     public ClassA a {get; set;}
}

4 个答案:

答案 0 :(得分:2)

设计A和设计B都很有用,但适用于不同的情况。

设计A的一个优点是,具有使用实例构造函数的参数初始化的私有实例字段,您知道字段a的“标识”不会被任何人(外部任何人)更改只要ClassB对象存在,类本身)。所以你可以根据这个做出假设。这为Design A提供了一种设计B缺乏的浅层不变性。

您还可以使用自动属性(而不是显式字段)创建设计A.只需创建自动属性set;的{​​{1}}访问者。

答案 1 :(得分:1)

这些设计都很好,视情况而定。 两者都是一种依赖注入,有4种类型的依赖注入:

  • 构造函数:design A
  • property:design B
  • 在调用方法
  • 时传递依赖关系
  • 环境背景

我不会详细说明你在这里没有使用的2种类型,但是它们与Mark Seeman的.NET中的依赖注入

中的其他2个一起讨论

设计A是构造函数依赖注入,其优点是它是最简单的依赖注入类型。您首选的依赖注入是这一个。如果注入的依赖项没有良好的默认值,这是完全正常的。构造对象后,依赖关系不会更改。 默认使用这种依赖注入可能会导致构造函数中包含许多参数的类。这被称为依赖注射。 我遵循Mark Seeman在他的书中所做的相同代码,所以我有这样的代码:

public class TekeningViewModel : ViewModelBase
{
    private readonly IUnitOfWorkAsync _unitOfWork;

    TekeningViewModel(IUnitOfWorkAsync _unitOfWork){
        if (unitOfWork == null)
        {
            throw new ArgumentNullException("unitOfWork");
        }
        _unitOfWork = unitOfWork;
    }
}

注意readonly类型的成员,并检查传递的参数是否为空。

如果注入依赖项有一个很好的默认值,

设计B是理想的。因为那时可能没有调用属性setter,并且自动在构造函数中设置了一个好的默认值。设计B也是strategy pattern。在设计A的地方,并不打算在飞行中改变为不同的依赖,在构造之后,即设计B,你可以做到这一点。在多线程环境中,这增加了以安全方式实现它的方式的复杂性。如上所述,设计B导致的代码多于设计A. 选择合适的默认值时必须小心,因为您不希望仅因默认值而创建对程序集的依赖关系。任何使用您的类的人,即使那些不使用该默认值的人,仍然会依赖包含该默认值的程序集。

进行依赖注入的第三种方式是这样的:

Aclass{
    void methodinjection(int a, Bclass b){
        ///
    }
}

并且执行依赖注入的第四种方式是这样的:

Aclass{
    void methodinjection(int a){
        AmbientContext::getInstance().getBclass();
        //....
    }
}

设计的复杂性从1增加到4。 类型4看起来像一个单例,它是一个反模式,所以它是我最不喜欢的依赖注入类型,但它确实有其优点。因为Ambient上下文本身应该使用前两种类型的依赖注入来创建,因此具有很大的灵活性。非常适合将交叉切割问题传递给应用程序,而不会使用太多参数污染构造函数。

答案 2 :(得分:0)

我对C ++的熟悉程度高于C#,但如果我理解正确,那就是用成员函数调用它。你的问题在这里得到了很好的回答:What is the use of making constructor private in a class?

答案所指的工厂模式是Factory Pattern的一部分;请参阅用例链接。

答案 3 :(得分:0)

我看到设计A只有一个带有一个参数的构造函数,并且没有默认的构造函数。所以这个设计强制规则只能通过在创建Class B对象时传递Class A的对象来创建对象类B,如果你不知道Class A的值,你就不能为B类创建对象,至少你有显式传递null。

在设计B中,没有这样的规则实施,因为有一个默认构造函数,你可以在创建B类后推迟A类对象的赋值。