PC Review


Reply
 
 
=?Utf-8?B?QW5kcmVh?=
Guest
Posts: n/a
 
      19th Feb 2005
Hi all,
I suspect a CLR Bug.
Please look like this code fragment !
My question is: why 0 (zero) is a special value in CLR ?!

Thanks all.

Code:

using System;

namespace CLR_Bug
{
class MainClass
{
[STAThread]
static void Main(string[] args)
{
TestClass mytestclass0=new TestClass(0); //Constructor with
SimpleEnum was called !
TestClass mytestclass1=new TestClass(1); //Constructor with object
was called !
TestClass mytestclassneg1=new TestClass(-1); //Constructor with object
was called !
TestClass mytestclass1000=new TestClass(1000);//Constructor with object
was called !
TestClass mytestclassStr=new TestClass("a"); //Constructor with object
was called !
Console.WriteLine("Why this behaviour ?!");
Console.ReadLine();
//Why 0 is a special value ?
}
}

class TestClass
{
public enum SimpleEnum { Red = 0, Blue = 1, Yellow = 2 }
public TestClass(SimpleEnum se) {
Console.WriteLine("Constructor with SimpleEnum was called !");
}
public TestClass(object obj) {
Console.WriteLine("Constructor with object was called !");
}
}
}

 
Reply With Quote
 
 
 
 
Mattias Sjögren
Guest
Posts: n/a
 
      19th Feb 2005

>My question is: why 0 (zero) is a special value in CLR ?!


This isn't a CLR issue. It's a C# compiler feature, since method
overload resolution is performed at compile time.

And the reason is that the literal 0 is implicitly convertible to any
enum type.



Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
 
Reply With Quote
 
=?Utf-8?B?QW5kcmVh?=
Guest
Posts: n/a
 
      19th Feb 2005
Hi Mattias,

thank you for your answer.

I don't think this is compiler feature for 2 reasons:
1) i know that .NET framework resolvs Calls for overloaded methods (with
object parameter) at run-time and not at compile time
(http://msdn.microsoft.com/library/de...bspec9_3_4.asp)
2) i have tried same test with VB.NET with same results. It is a vb.net
compiler feature too ?!

Thanks in advance.

this is VB.NET code i tried:

Imports System

Module Module1
Sub Main()
Dim mytestclass0 As New TestClass(0) 'Constructor with
SimpleEnum was called !
Dim mytestclass1 As New TestClass(1) 'Constructor with object
was called !
Dim mytestclassneg1 As New TestClass(-1) 'Constructor with object
was called !
Dim mytestclass1000 As New TestClass(1000) 'Constructor with object
was called !
Dim mytestclassStr As New TestClass("a") 'Constructor with object
was called !
Console.WriteLine("Why this behaviour ?!")
Console.ReadLine()
'Why 0 is a special value ?
End Sub
End Module

Class TestClass
Public Enum SimpleEnum
Red = 0
Blue = 1
Yellow = 2
End Enum

Public Sub New(ByVal se As SimpleEnum)
Console.WriteLine("Constructor with SimpleEnum was called !")
End Sub
Public Sub New(ByVal obj As Object)
Console.WriteLine("Constructor with object was called !")
End Sub
End Class



you wrote:
"reason is that the literal 0 is implicitly convertible to any enum type".

Ok ... but why this behaviour only for 0 (zero) and not for 1 (one) !?

They are both int !



"Mattias Sjögren" wrote:

>
> >My question is: why 0 (zero) is a special value in CLR ?!

>
> This isn't a CLR issue. It's a C# compiler feature, since method
> overload resolution is performed at compile time.
>
> And the reason is that the literal 0 is implicitly convertible to any
> enum type.
>
>
>
> Mattias
>
> --
> Mattias Sjögren [MVP] mattias @ mvps.org
> http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
> Please reply only to the newsgroup.
>

 
Reply With Quote
 
Jon Skeet [C# MVP]
Guest
Posts: n/a
 
      19th Feb 2005
Andrea <(E-Mail Removed)> wrote:
> Hi Mattias,
>
> thank you for your answer.
>
> I don't think this is compiler feature for 2 reasons:
> 1) i know that .NET framework resolvs Calls for overloaded methods (with
> object parameter) at run-time and not at compile time


That's not true in general. Use ildasm to look at the generated code,
and you'll see exactly what method is going to be invoked in your case.

> (http://msdn.microsoft.com/library/de...rary/en-us/vbl
> s7/html/vblrfvbspec9_3_4.asp)


That is talking about the case where strict semantics are not being
used, which isn't even available as an option in C#, so can't possibly
apply to the C# code you posted. It's not normally applicable to well-
written VB.NET code either, as most VB.NET code should have Option
Strict turned on.

> 2) i have tried same test with VB.NET with same results. It is a vb.net
> compiler feature too ?!


Yes. In both languages, there's an implicit conversion from the literal
0 to any enum. (See section 8.8 of the VB.NET spec, and 13.1.3 of the
ECMA C# spec.)

> you wrote:
> "reason is that the literal 0 is implicitly convertible to any enum type".
>
> Ok ... but why this behaviour only for 0 (zero) and not for 1 (one) !?
>
> They are both int !


There are various times when it's useful to have such an implicit
conversion - not least when checking for bitwise flags:

if ((testValue & MyEnum.SomeFlag) != 0)

is simpler than

if ((testValue & MyEnum.SomeFlag) != (MyEnum)0)

and is still perfectly clear.

--
Jon Skeet - <(E-Mail Removed)>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
 
Reply With Quote
 
=?Utf-8?B?QW5kcmVh?=
Guest
Posts: n/a
 
      19th Feb 2005
Hi Jon,

please look this code:

SqlParameter p0=new SqlParameter("@myparam0",0);
//produce new SqlParameter("@myparam",SqlDbType.BigInt) with DBNull as
parameter's Value
//BigInt because SqlDbType.BigInt is the first value in SqlDbType enum
SqlParameter p1=new SqlParameter("@myparam1",1);
//produce new SqlParameter("@myparam",1) with 1 as paramter's Value and Int
as SqlDbType

if VB.NET and C# compilers has this behaviour ...
If there's an implicit conversion from the literal 0 to enum ...
if i try to use p0.Value in this case i have i logical bug ... i receive an
unexpeted NullReferenceExpetion

Thank you.
Andrea.

"Jon Skeet [C# MVP]" wrote:

> Andrea <(E-Mail Removed)> wrote:
> > Hi Mattias,
> >
> > thank you for your answer.
> >
> > I don't think this is compiler feature for 2 reasons:
> > 1) i know that .NET framework resolvs Calls for overloaded methods (with
> > object parameter) at run-time and not at compile time

>
> That's not true in general. Use ildasm to look at the generated code,
> and you'll see exactly what method is going to be invoked in your case.
>
> > (http://msdn.microsoft.com/library/de...rary/en-us/vbl
> > s7/html/vblrfvbspec9_3_4.asp)

>
> That is talking about the case where strict semantics are not being
> used, which isn't even available as an option in C#, so can't possibly
> apply to the C# code you posted. It's not normally applicable to well-
> written VB.NET code either, as most VB.NET code should have Option
> Strict turned on.
>
> > 2) i have tried same test with VB.NET with same results. It is a vb.net
> > compiler feature too ?!

>
> Yes. In both languages, there's an implicit conversion from the literal
> 0 to any enum. (See section 8.8 of the VB.NET spec, and 13.1.3 of the
> ECMA C# spec.)
>
> > you wrote:
> > "reason is that the literal 0 is implicitly convertible to any enum type".
> >
> > Ok ... but why this behaviour only for 0 (zero) and not for 1 (one) !?
> >
> > They are both int !

>
> There are various times when it's useful to have such an implicit
> conversion - not least when checking for bitwise flags:
>
> if ((testValue & MyEnum.SomeFlag) != 0)
>
> is simpler than
>
> if ((testValue & MyEnum.SomeFlag) != (MyEnum)0)
>
> and is still perfectly clear.
>
> --
> Jon Skeet - <(E-Mail Removed)>
> http://www.pobox.com/~skeet
> If replying to the group, please do not mail me too
>

 
Reply With Quote
 
Jon Skeet [C# MVP]
Guest
Posts: n/a
 
      19th Feb 2005
Andrea <(E-Mail Removed)> wrote:
> please look this code:
>
> SqlParameter p0=new SqlParameter("@myparam0",0);
> //produce new SqlParameter("@myparam",SqlDbType.BigInt) with DBNull as
> parameter's Value
> //BigInt because SqlDbType.BigInt is the first value in SqlDbType enum
> SqlParameter p1=new SqlParameter("@myparam1",1);
> //produce new SqlParameter("@myparam",1) with 1 as paramter's Value and Int
> as SqlDbType
>
> if VB.NET and C# compilers has this behaviour ...


Which they do.

> If there's an implicit conversion from the literal 0 to enum ...


Which there is.

> if i try to use p0.Value in this case i have i logical bug ... i receive an
> unexpeted NullReferenceExpetion


Yes, you do. It's an unfortunate but rare consequence of the
overloading rules, which make life better in the majority of cases. Of
course, the same is true if you want to make a sql parameter where the
actual *value* is a SqlDbType. Unlikely, but still problematic due to
the constructor overloading. Fortunately, a simple cast to object will
work in both cases.

This isn't a bug - it's a design decision which you may not agree with,
but everything's behaving as specified, I believe.

--
Jon Skeet - <(E-Mail Removed)>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off



Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 04:51 AM.