I am curious as to why the following logic is allowed in C#
private static void Foo(Func<Exception, string> func)
{
try
{
// ...
}
catch (ArgumentException ex)
{
func(ex);
}
}
whereas this is not
private static void Foo<T>(Func<T, string> func) where T : Exception
{
try
{
// ...
}
catch (ArgumentException ex)
{
func(ex);
}
}
From what I understand, since the Func<in TArg1, out TResult>
delegate has a contravariant parameter since .NET 4.0, the first scenario is not problem, but why does switching to a constrained generic type change the ability of the compiler to apply this contravariance ?
Your first function will compile, however due to contravariance of Func
parameters, you can only pass a Func
with a parameter which is a supertype of Exception
e.g.
Func<object, string> f = o => o.ToString();
Foo(f);
this is not the case in the second example, which would require you to pass a Func
with a parameter which is a subtype of Exception
e.g
Func<InvalidOperationException> f = o => ...
which would not be safe.