1

People always define a private member and then pass constructor argument value to it ,like Design A. But i can't understand the benefit to doing this, because the private member do not get a copy (i mean a deep clone) ,so why not just go with Design B ?

Design A:

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

public class ClassB 
{

    private ClassA a ;

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

Design B:

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

public class ClassB 
{
     public ClassA a {get; set;}
}
Invincible
  • 29
  • 3

4 Answers4

2

Both Design A and Design B can be useful, but for different situations.

One advantage of Design A, having a private instance field that is initialized with a parameter of the instance constructor, is that you know that the "identity" of the field a is not changed by anyone (anyone outside the class itself) as long as the ClassB object is in existence. So you can make assumptions based on that. This gives Design A a kind of shallow immutability that Design B lacks.

You can also make Design A with an auto-property (rather than an explicit field); just make the set; accessor of the auto-property private.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
1

Both those designs are fine, depending on the situation. Both are a kind of dependency injection, there are 4 types of dependency injection:

  • constructor : design A
  • property : design B
  • pass dependency when calling method
  • ambient context

I will not elaborate on the 2 types you don't use here but they are discussed along with the other 2 in Dependency Injection in .NET of Mark Seeman

design A is constructor dependency injection and has the advantage that it is the most simple type of dependency injection. Your first choice of dependency injection is this one. If there is no good default for the dependency being injected, this is perfectly fine. The dependency does not change after the object is constructed. Defaulting to this kind of dependency injection can lead to classes with many parameters in the constructor. This is referred to as dependency over injection. I follow the same code as Mark Seeman does in his book so I have code like this :

public class TekeningViewModel : ViewModelBase
{
    private readonly IUnitOfWorkAsync _unitOfWork;

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

note the readonly type of member and the check that the parameter being passed is not null.

design B is ideal if there is a good default for the dependency being injected. Because then the property setter is perhaps not called, and a good default is set in the constructor automatically. design B is also a strategy pattern. Where in design A it is not the intention to change to a different dependency on the fly, after construction that is, with design B you can do that. In a multi threaded environment this adds complexity to the way you have to implement it in a safe way. As explained design B leads to more code than design A. Care must be taken when choosing a good default, because you don't want to create a dependency to an assembly just because of the default. Anyone using your class even those that don't use that default still would have a dependency towards the assembly that contains that default.

the third way to do dependency injection is like this :

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

and the fourth way to do dependency injection is like this :

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

the complexity of the design keeps growing from 1 to 4. Type 4 looks like a singleton which is an antipattern so it is my least favorite type of dependency injection but it does have its merit. Because the Ambient context itself should be created using dependency injection of the first 2 types and thus has a lot of flexibility. Ideal to pass cross cutting concerns to the application without polluting the constructor with too many parameters.

Philip Stuyck
  • 7,344
  • 3
  • 28
  • 39
  • Thanks for your detailed answer. From my opinion , the most valuable part of Design A is it reduce the complexity In a multiple thread environment. – Invincible Apr 04 '15 at 10:10
0

My familiarity is greater with C++ than C#, but if I understand correctly, it is to call it with member functions. A similar question to yours was answered really well here: What is the use of making constructor private in a class?

The factory pattern the answer refers to is part of the Factory Pattern; refer to the link for use cases.

Community
  • 1
  • 1
Boris
  • 566
  • 5
  • 21
0

I see design A has only a constructor with one parameter, and there is no default constructor. So this design enforce rule that object class B can be created only by passing object of Class A. at the time of creating Class B object, if you dont know the value of Class A, you cannot create object for class B, atleast you have to explicitly pass null.

In design B, there is no such rule enforcement as there is a default constructor, you can postpone the assignment of class A object after you create Class B.

Alagesan Palani
  • 1,984
  • 4
  • 28
  • 53