Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't type constraints part of the method signature?

UPDATE: As of C# 7.3, this should no longer be an issue. From the release notes:

When a method group contains some generic methods whose type arguments do not satisfy their constraints, these members are removed from the candidate set.

Pre C# 7.3:

So I read Eric Lippert's 'Constraints are not part of the signature', and now I understand that the spec specifies that type constraints are checked AFTER overload resolution, but I'm still not clear on why this MUST be the case. Below is Eric's example:

static void Foo<T>(T t) where T : Reptile { }
static void Foo(Animal animal) { }
static void Main() 
{ 
    Foo(new Giraffe()); 
}

This doesn't compile because overload resolution for: Foo(new Giraffe()) infers that Foo<Giraffe> is the best overload match but then the type constraints fail and a compile-time error is thrown. In Eric's words:

The principle here is overload resolution (and method type inference) find the best possible match between a list of arguments and each candidate method’s list of formal parameters. That is, they look at the signature of the candidate method.

Type constraints are NOT part of the signature, but why can't they be? What are some scenarios where it is a bad idea to consider type constraints part of the signature? Is it just difficult or impossible to implement? I'm not advocating that if the best chosen overload is for whatever reason impossible to call then silently fallback to the second best; I would hate that. I'm just trying to understand why type constraints can't be used to influence the choosing of the best overload.

I'm imagining that internally in the C# compiler, for overload resolution purposes only (it doesn't permanently rewrite the method), the following:

static void Foo<T>(T t) where T : Reptile { }

gets transformed to:

static void Foo(Reptile  t) { }

Why can't you sort of "pull in" the type constraints into the formal parameter list? How does this change the signature in any bad way? I feel like it only strengthens the signature. Then Foo<Reptile> will never be considered as an overload candidate.

Edit 2: No wonder my question was so confusing. I didn't properly read Eric's blog and I quoted the wrong example. I've edited in the example I think more appropriate. I've also changed the title to be more specific. This question doesn't seem as simple as I first imagined, perhaps I'm missing some important concept. I'm less sure that this is stackoverflow material, it may be best for this question/discussion to be moved elsewhere.

like image 794
Daryl Avatar asked Feb 25 '12 03:02

Daryl


1 Answers

The C# compiler has to not consider type constraints as part as the method signature because they are not part of the method signature for the CLR. It would be disastrous if the overload resolution worked differently for different languages (mainly due to the dynamic binding that may happen at runtime and should not be different from one language to another, or else all hells would break loose).

Why was it decided that these constraints would not be part of the method signature for the CLR is another question alltogether, and I could only make ill informed suppositions about that. I'll let the people in the know answer that.

like image 62
Falanwe Avatar answered Sep 28 '22 09:09

Falanwe