The new keyword causes our codes to get coupled.
Let's take this simple example:
interface IShape { public string Name { get; } } class Square : IShape { public string Name { get; private set; } public Square() { Name = "Square"; } } class Circle : IShape { public string Name { get; private set; } public Circle() { Name = "Circle"; } } class ShapeHolder { public IShape Shape { get; private set; } ShapeHolder() { shape = new Square(); } }
If we see the above example, even though we have used an interface 'IShape', our ShapeHolder is now tightly coupled to the Square instance. It can never ever hold an instance of a circle. This may seem fine but this causes two major problems:
- Unit Tests: There's no way to test ShapeHolder independently of Square class. Any test written for ShapeHolder would end up working with a concrete instance of Square class. If Square class was modified later to start using network access or a db call, unit tests of ShapeHolder may start failing or take up huge amounts of time, as the testing environment won't have the necessary setups.
- Extensibility: The above code doesn't show run time polymorphism. In future if a new shape comes in, which must work with the ShapeHolder class, we will have to modify the ShapeHolder class too. This may in-turn cause some other class to be modified. This is a violation of open closed principle.