I'm learning about C# extension methods at the moment. I have read in a couple of places that adding members to classes reduces backwards compatibility for code that uses those classes.
I've read this here: https://blogs.msdn.microsoft.com/vbteam/2007/03/10/extension-methods-best-practices-extension-methods-part-6/
And page 418 of Troelson's Pro C# book.
I'm afraid this doesn't make sense to me. Surely any code that uses instances of those classes as they WERE before extra members were added (without using extension methods, just by adding them to the class), will still be able to call all the old methods, properties, fields and constructors just like before, as they haven't changed. Even if the new members can change the state of the object, they will never be called in the old code, so therefore the code is backwards compatible.
What am I not seeing here?
Here's one possible way adding a new method could actually break client code...
void Main()
{
var oldFoo = new OldFoo();
var oldResult = oldFoo.Calculate(2, 2); // 4
var newFoo = new NewFoo();
var newResult = newFoo.Calculate(2, 2); // 0
}
public class OldFoo
{
public int Calculate(params int[] values)
{
return values.Sum();
}
}
public class NewFoo
{
public int Calculate(params int[] values)
{
return values.Sum();
}
public int Calculate(int value1, int value2)
{
return value1 - value2;
}
}
And here's another way, specifically dealing with an extension method...
Initially, the client defines an extension method to give Foo
the ability to Combine
:
void Main()
{
var foo = new Foo();
var result = foo.Combine(2, 2); // "22"
}
public static class Extensions // added by client
{
public static string Combine(this Foo foo, params int[] values)
{
return string.Join(string.Empty, values.Select(x => x.ToString()));
}
}
public class Foo { }
Later, the developer of Foo
adds a new Combine
method to the class:
void Main()
{
var foo = new Foo();
var result = foo.Combine(2, 2); // 4
}
public static class Extensions
{
public static string Combine(this Foo foo, params int[] values)
{
return string.Join(string.Empty, values.Select(x => x.ToString()));
}
}
public class Foo
{
public int Combine(params int[] values)
{
return values.Sum();
}
}
Note that the extension method gets effectively blocked or shadowed by the new Combine
instance method.