Errors in C# 2.0 specification?

G

Guest

I guess there are many errors in current version of C# 2.0 specification.
Let's see one of many examples(I use C# Express beta 2, but think you can use
any C#2.0 compiler). So, in document
http://download.microsoft.com/downl...-48fe-9e5e-f87a44af3db9/specificationver2.doc
in section "20.1.8 Overloading in generic classes" anyone can read:
....
The following examples show overloads that are valid and invalid according
to this rule:
interface I1<T> {...}
interface I2<T> {...}
class G1<U>
{
long F1(U u); // Invalid overload, G<int> would have two
int F1(int i); // members with the same signature
void F2(U u1, U u2); // Valid overload, no type argument for U
void F2(int i, string s); // could be int and string simultaneously
void F3(I1<U> a); // Valid overload
void F3(I2<U> a);
void F4(U a); // Valid overload
void F4(U[] a);
}
class G2<U,V>
{
void F5(U u, V v); // Invalid overload, G2<int,int> would have
void F5(V v, U u); // two members with the same signature
void F6(U u, I1<V> v); // Invalid overload, G2<I1<int>,int> would
void F6(I1<V> v, U u); // have two members with the same signature
void F7(U u1, I1<V> v2); // Valid overload, U cannot be V and I1<V>
void F7(V v1, U u2); // simultaneously
void F8(ref U u); // Invalid overload
void F8(out V v);
}
class C1 {...}
class C2 {...}
class G3<U,V> where U: C1 where V: C2
{
void F9(U u); // Invalid overload, constraints on U and V
void F9(V v); // are ignored when checking overloads
}

Ok, let's take class G2 and interface I1 only
interface I1<T> {...}
....
class G2<U,V>
{
void F5(U u, V v); // Invalid overload, G2<int,int> would have
void F5(V v, U u); // two members with the same signature
void F6(U u, I1<V> v); // Invalid overload, G2<I1<int>,int> would
void F6(I1<V> v, U u); // have two members with the same signature
void F7(U u1, I1<V> v2); // Valid overload, U cannot be V and I1<V>
void F7(V v1, U u2); // simultaneously
void F8(ref U u); // Invalid overload
void F8(out V v);
}
and analyze its comments:
void F5(U u, V v); // Invalid overload, G2<int,int> would have
void F5(V v, U u); // two members with the same signature
/*/
Correct, but ONLY if we create something like G2<int,int> AND(exactly AND,
just fact of creating G2<int,int> is OK) if we try call F5. If we create
G2<int, long> and call g2instance.F5((long)4, 8) all fine.
Conclusion: semi-error. In most cases this overload IS valid.

void F6(U u, I1<V> v); // Invalid overload, G2<I1<int>,int> would
void F6(I1<V> v, U u); // have two members with the same signature
/*/
Incorrect, I1<int> and int are different types and they occupy different
positions in "left-to-right-order" within parameters-list.
Conclusion: Error. This is 100% valid overload.

void F7(U u1, I1<V> v2);// Valid overload, U cannot be V and I1<V>
void F7(V v1, U u2); // simultaneously
/*/
Conclusion: Absolutely correct. This is 100% valid overload

void F8(ref U u); // Invalid overload
void F8(out V v);
/*/
Incorrect, the ref and out modifiers ARE PART of a method's signature
Conclusion: Error. This is 100% valid overload.

Grand total: 4 assertions, 3 errors!! Am I right?
 
W

Willy Denoyette [MVP]

Smarty said:
I guess there are many errors in current version of C# 2.0 specification.
Let's see one of many examples(I use C# Express beta 2, but think you can
use
any C#2.0 compiler). So, in document
http://download.microsoft.com/downl...-48fe-9e5e-f87a44af3db9/specificationver2.doc
in section "20.1.8 Overloading in generic classes" anyone can read:
...


You refer to an old draft of the specs, you posted the question on another
thread but you picked the wrong answer and downloaded an old draft of the
specification.
Also note this NG is for released products only, You should post v2.0 beta
questions/issues to the whidbey forums http://forums.microsoft.com/msdn/ and
if you think you found a bug (product, docs etc...) you should file an issue
to http://lab.msdn.microsoft.com/productfeedback/default.aspx.

Willy.
 
D

Daniel O'Connell [C# MVP]

class G2 said:
{
void F5(U u, V v); // Invalid overload, G2<int,int> would have
void F5(V v, U u); // two members with the same signature
void F6(U u, I1<V> v); // Invalid overload, G2<I1<int>,int> would
void F6(I1<V> v, U u); // have two members with the same signature
void F7(U u1, I1<V> v2); // Valid overload, U cannot be V and I1<V>
void F7(V v1, U u2); // simultaneously
void F8(ref U u); // Invalid overload
void F8(out V v);
}
and analyze its comments:
void F5(U u, V v); // Invalid overload, G2<int,int> would have
void F5(V v, U u); // two members with the same signature
/*/
Correct, but ONLY if we create something like G2<int,int> AND(exactly AND,
just fact of creating G2<int,int> is OK) if we try call F5. If we create
G2<int, long> and call g2instance.F5((long)4, 8) all fine.
Conclusion: semi-error. In most cases this overload IS valid.

Sorry, but if one situation comes up where it is not valid, the overload
cannot be valid. This is correct.
void F6(U u, I1<V> v); // Invalid overload, G2<I1<int>,int> would
void F6(I1<V> v, U u); // have two members with the same signature
/*/
Incorrect, I1<int> and int are different types and they occupy different
positions in "left-to-right-order" within parameters-list.
Conclusion: Error. This is 100% valid overload.

Incorrect again. You made a mistake in reading this. Consider G2<I1<int>,
int> again, notice that you result in
void F6(I1<int>,I1<int>) for void F6(U u, I1<V> v)
and
U u); said:
void F8(ref U u); // Invalid overload
void F8(out V v);
/*/
Incorrect, the ref and out modifiers ARE PART of a method's signature
Conclusion: Error. This is 100% valid overload.

Actually, the language doesn't permit that in any circumstance, so its not
valid on its face. ref and out generate identical method signatures at the
CLR level, with ref or out one being marked by an attribute.
 
G

Guest

Willy Denoyette said:
You refer to an old draft of the specs, you posted the question on another
thread but you picked the wrong answer and downloaded an old draft of the
specification.
Also note this NG is for released products only, You should post v2.0 beta
questions/issues to the whidbey forums http://forums.microsoft.com/msdn/ and
if you think you found a bug (product, docs etc...) you should file an issue
to http://lab.msdn.microsoft.com/productfeedback/default.aspx.

Willy.
OK, thanks. I will try this approach.
 
G

Guest

Daniel O'Connell said:
Sorry, but if one situation comes up where it is not valid, the overload
cannot be valid. This is correct.

H-m-m... May be. But think it should be marked plain - "not valid in
exactly(and only) one situation..."
Incorrect again. You made a mistake in reading this. Consider G2<I1<int>,
int> again, notice that you result in
void F6(I1<int>,I1<int>) for void F6(U u, I1<V> v)
and
void F6(I1<int>,I1<int>) for for void F6(I1<V>, U u);

but said:
Actually, the language doesn't permit that in any circumstance, so its not
valid on its face. ref and out generate identical method signatures at the
CLR level, with ref or out one being marked by an attribute.

Let's say simple - ref/out ARE PART of a method's signature or they are NOT?
Small snippet:

using System;

class Test
{
class G2<U, V>
{
public void F8(ref U u) { Console.WriteLine("F8 with ref"); }
public void F8(out V v) { Console.WriteLine("F8 with out"); v =
default(V); }
}

class App
{
static void Main()
{
G2<int, int> g2a = new G2<int, int>();
int i = 7;
g2a.F8(ref i);
g2a.F8(out i);
}
}
}
 
W

Willy Denoyette [MVP]

Smarty said:
H-m-m... May be. But think it should be marked plain - "not valid in
exactly(and only) one situation..."


Yes, this is entirely my fault. I check this code against G2<int, int>,
but


Let's say simple - ref/out ARE PART of a method's signature or they are
NOT?
Small snippet:

using System;

class Test
{
class G2<U, V>
{
public void F8(ref U u) { Console.WriteLine("F8 with ref"); }
public void F8(out V v) { Console.WriteLine("F8 with out"); v =
default(V); }
}

class App
{
static void Main()
{
G2<int, int> g2a = new G2<int, int>();
int i = 7;
g2a.F8(ref i);
g2a.F8(out i);
}
}
}

The latest and final draft has corrected this,

void F8(ref U u) {...}
void F8(out V v) {....}

are valid overloads.


Willy.
 
D

Daniel O'Connell [C# MVP]

Willy Denoyette said:
The latest and final draft has corrected this,

void F8(ref U u) {...}
void F8(out V v) {....}

are valid overloads.

That is troubling, it really is. The compiler has, to this point, disallowed

F8 (ref int x)
F8 (out int x)

why would it be allowed in this case if V and U are not constrained to be
mutually exclusive in some way? Did the spec change to allow overloading by
ref and out in all methods(I don't think this would even work cleanly)?

While I suppose it is possible to achieve techincally with generics, it
still seems to be quite inconsistent.
 
W

Willy Denoyette [MVP]

Daniel O'Connell said:
That is troubling, it really is. The compiler has, to this point,
disallowed

F8 (ref int x)
F8 (out int x)

why would it be allowed in this case if V and U are not constrained to be
mutually exclusive in some way? Did the spec change to allow overloading
by ref and out in all methods(I don't think this would even work cleanly)?

While I suppose it is possible to achieve techincally with generics, it
still seems to be quite inconsistent.

You are right, it is inconsistent, and IMO it's wrong. It looks like the
inference process (wrongly) considers ref/out as part of the signature and
picks the best method and as such by-passing overload resolution which would
throw an "ambiguity" error.

Do you file a bug on Ladybug, or shall I?

Willy.
 
G

Guest

Willy Denoyette said:
The latest and final draft has corrected this,

void F8(ref U u) {...}
void F8(out V v) {....}

are valid overloads.


Willy.

Yes, you are totally right. But when I wrote my very first question I had
"May,2004" version only. Now this moment resolved, at last. Thanks for your
participation!
 
G

Guest

Willy Denoyette said:
You are right, it is inconsistent, and IMO it's wrong. It looks like the
inference process (wrongly) considers ref/out as part of the signature and
picks the best method and as such by-passing overload resolution which would
throw an "ambiguity" error.

Do you file a bug on Ladybug, or shall I?

Willy.

I think there is no contradiction with specification(latest version) which
say:
While signatures _as declared_(i.e. F8 (ref/out int x) case) must be unique,
it is possible that _substitution of type arguments_(i.e. G2<U, V> case)
results in _identical_(!) signatures. The tie-breaking rules of overload
resolution will pick the most specific one.

The game going by the rules.
 
W

Willy Denoyette [MVP]

Smarty said:
I think there is no contradiction with specification(latest version) which
say:
While signatures _as declared_(i.e. F8 (ref/out int x) case) must be
unique,
it is possible that _substitution of type arguments_(i.e. G2<U, V> case)
results in _identical_(!) signatures. The tie-breaking rules of overload
resolution will pick the most specific one.

The game going by the rules.

That's right, I was reading through the new specs today and it's also
confirmed by Rick Byers (MSFT), the specs and the compiler are conform the
changes made after Beta1.
Case closed :)

Willy.
 
D

Daniel O'Connell [C# MVP]

I think there is no contradiction with specification(latest version)
That's right, I was reading through the new specs today and it's also
confirmed by Rick Byers (MSFT), the specs and the compiler are conform the
changes made after Beta1.
Case closed :)

Glad there is an answer atleast, ;). I still think its troublingly
inconsistent, but not that big of a deal.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top