Evil Code #12: Tuple Parameter – Overloads and Overrides

Tuples is an interesting subject to go back to due to certain peculiar qualities it possess. In this section, we would address some of them.

To begin with, however, we will address how to tuples behave during method overloads – a pattern it share with rest of .Net. Consider the following code.

public class Foo
{
	public void Bar((int,object) param)
	{
	}
	
	public void Bar((int,dynamic) param)
	{
	}
}

Would the above code compile ? If not, why ?

Well, it doesn’t compile – of course. The compiler would complain that

Type 'Foo' already defines a member called 'Bar' with the same parameter types

This is because there is an identity conversion between object and dynamic, which results in compiler detecting both methods as signature with same parameter types. This is similiar to how it would have been if you had defined an overload as following.

public void Bar(object param)
{
}

public void Bar(dynamic param)
{
}

As one would guess, that isn’t allowed either.

The second scenario we would be checking is with regard to inheritance or interface implementations. Consider the following code.

public interface IBar
{
	void Foo((object left,object right) param);
}

public class Bar:IBar
{
	public void Foo((object left, dynamic right) param)
	{
	}
}

Now considering the identity conversion between object and dynamic, it is easy to guess that this would be allowed. However, the nasty part shows when you vary the name of the tuple variable. Consider the following code, where i have renamed the right parameter in tuple as center.

public interface IBar
{
	void Foo((object left,object right) param);
}

public class Bar:IBar
{
	public void Foo((object left, object center) param)
	{
	}
}

Notice, I have retained the types of each element and arity of the tuple. The only thing that has changed is the name of one of the elements in the tuple. This breaks the code with following exception.

The tuple element names in the signature of method 'Bar.Foo((object left, object center))' must match the tuple element names of interface method 'IBar.Foo((object left, object right))' (including on the return type).

Isn’t that interesting ? I would rather use the word scary. Imagine as a library developer you rename of the tuple parameters in your API and it breaks all the clients.

This would be one change I wish the elite team working .Net manages to fix as this is quite unlike rest of the .Net.