Can a generic class cause identical signature overloads?

Possible duplicate:
General methods and method overloading

Ok, I accidentally hit this ... Providing this situation:

class Program { static void Main( string[ ] args ) { var obj = new gen<int>( ); Console.Write( obj[ 1 ] ); Console.ReadKey( ); } } class gen<T> { public int this[ T i ] { get { return 2; } } public int this[ int i ] { get { return 1; } } } 

It will always print 1. I would expect the compiler to complain, or the runtime to crash and burn and melt the CPU, but no, it is happy to print '1'

Of course, I can make a choice to return if I use any other type for a general parameter. For a giggle, I'm trying to use UInt as a generic type of parmater, and I can distinguish between calls, so the questions are:

  • Why is C # not worried? Shouldn't Anders Halesberg feel restless in power?

  • How can I restrict a general parameter from certain types? Since this T can be anything but ints (but for a long time everything is fine)

+4
source share
4 answers

I believe this is stated in section 7.5.3.2 of the C # 4 specification (Better Function Member).

  • Otherwise, if M P has more specific types of parameters than M Q, then M P is better than MQ [...]
    • The type parameter is less specific than the nontype parameter.
    • [...]

So, a member with a parameter T less specific than a member with an int parameter.

Try to create your own path out of this, just without overloading it. Of course, this is difficult for indeducers, but you can always provide methods (or perhaps just like a recession).

EDIT: note that if you have overloaded methods where both are type parameters, the compiler will complain:

 public class Foo<T1, T2> { public void Bar(T1 t1) {} public void Bar(T2 t2) {} } ... Foo<int, int> foo = new Foo<int, int>(); foo.Bar(10); // Error 

Here, none of the methods is more specific.

How can I restrict a general parameter from certain types? Since this T can be anything but ints (but for a long time everything is fine)

This is really a completely separate issue, but in principle you cannot. You can restrict type parameters in various ways, but not by explicitly including and excluding types. See the MSDN restrictions page for more information.

+9
source

As Eric Lippert says :

The C # specification states that when you have a choice between calling ReallyDoIt (string) and ReallyDoIt (string), that is, when you choose between two methods that have identical signatures, but receive this signature through a common substitution - then we select " natural "signature" over a "substituted" signature.

This process is also described in C # spec 7.5.3.2 (a more efficient member of a function):

In the case when the sequence of parameter types {P1, P2, ..., PN} and {Q1, Q2, ..., QN} are equivalent (that is, each Pi has an identity transformation to the corresponding Qi), the following rules are tie- breaks are used to determine the best member of a function.

  • If MP is not a general method, and MQ is a general method, then MP is better than MQ (as John pointed out, this is true if you have a general method and not a common type)
  • ...
  • Otherwise, if MP has more specific parameter types than MQ, MP is better than MQ. Let {R1, R2, ..., RN} and {S1, S2, ..., SN} be unreasonable and unexpanded parameter types MP and MQ. Types of MP parameters are more specific than MQ, if for each parameter RX is no less specific than SX, and for at least one parameter RX is more specific than SX:

    • The type parameter is less specific than the non-type parameter (this is your case - therefore the methods are not general, and the type of the proposed parameter is equal to the non-generated type of the parameters)
+8
source

The C # compiler always chooses a more specific and more general method if the call can match both =). Thatโ€™s why he doesnโ€™t worry, he just follows his own rules.

0
source

The C # compiler is not keen on the fact that both methods are valid and both can be called.

Here is an example returning "2":

 Gen<Form> gen = new Gen<Form>(); textBox1.Text = gen[this].ToString(); 

Where "this" is the form. Of course, using index access as an object instead of a number ... Well, whatever that is, it works.

But, like everyone else, the compiler will prefer the explicit implicitly.

-2
source

Source: https://habr.com/ru/post/1441577/


All Articles