473,396 Members | 1,816 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

shouldn't if (this!=null) generate a warning?

Shouldn't if (this!=null) generate a compiler warning?

in fact, it does not.
May 26 '06 #1
16 2320

cody wrote:
Shouldn't if (this!=null) generate a compiler warning?


What warning would you like to see?

--
Larry Lard
Replies to group please

May 26 '06 #2
"Larry Lard" <la*******@hotmail.com> wrote in message
news:11*********************@i39g2000cwa.googlegro ups.com...
cody wrote:
Shouldn't if (this!=null) generate a compiler warning?


What warning would you like to see?


I see what the OP is driving at - sort of like asking Descartes if it's
possible to think you don't exist... :-)
May 26 '06 #3

Mark Rae wrote:
"Larry Lard" <la*******@hotmail.com> wrote in message
news:11*********************@i39g2000cwa.googlegro ups.com...
cody wrote:
Shouldn't if (this!=null) generate a compiler warning?


What warning would you like to see?


I see what the OP is driving at - sort of like asking Descartes if it's
possible to think you don't exist... :-)


I see what they're driving at too, and I'm trying to be Socratic :)

--
Larry Lard
Replies to group please

May 26 '06 #4

"cody" <de********@gmx.de> wrote in message
news:uS**************@TK2MSFTNGP05.phx.gbl...
Shouldn't if (this!=null) generate a compiler warning?

in fact, it does not.

Maybe we need a "something" to go along with "null", then we could just do
if (this == something)

:-)
May 26 '06 #5
the same warning that is generated for other expressions which the compiler
determines to always be true or to alway be false.
for example an expression like "if (this is string)" will generate a warning
(if the class is not system.string or course).

--

"Larry Lard" <la*******@hotmail.com> schrieb im Newsbeitrag
news:11*********************@i39g2000cwa.googlegro ups.com...

cody wrote:
Shouldn't if (this!=null) generate a compiler warning?


What warning would you like to see?

--
Larry Lard
Replies to group please

May 26 '06 #6
"james" <ja***@com.com> wrote in message
news:44**********************@news.zen.co.uk...
Maybe we need a "something" to go along with "null", then we could just do
if (this == something)


Ah yes, but just because something isn't nothing doesn't imply that it is
something...

You know what they say: "you can take a horse to water but a pencil must be
lead"

And, for the extremely politically incorrect among us, "one in Kate Bush is
worth ten in the hand..."
May 26 '06 #7
>the same warning that is generated for other expressions which the compiler
determines to always be true or to alway be false.


But in this case the condition can evaluate to false. While you're not
allowed to do it in C#, the CLR and other languages let you call
instance methods on a null reference.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
May 26 '06 #8
Great. So we would always have to put if (this!=null) throw new
ArgumentNullException(); in every method just to make sure :-)

"Mattias Sjögren" <ma********************@mvps.org> schrieb im Newsbeitrag
news:uM**************@TK2MSFTNGP05.phx.gbl...
the same warning that is generated for other expressions which the
compiler
determines to always be true or to alway be false.


But in this case the condition can evaluate to false. While you're not
allowed to do it in C#, the CLR and other languages let you call
instance methods on a null reference.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

May 27 '06 #9
Mattias Sjögren <ma********************@mvps.org> wrote in
news:uM**************@TK2MSFTNGP05.phx.gbl:
the same warning that is generated for other expressions which the
compiler determines to always be true or to alway be false.


But in this case the condition can evaluate to false. While you're not
allowed to do it in C#, the CLR and other languages let you call
instance methods on a null reference.
Mattias


But we're discussing the CSharp compiler...
May 27 '06 #10
Martin Milan <I8**@m.i.do> wrote:
But we're discussing the CSharp compiler...


A class written with C#, and compiled with the C# compiler, may be
instantiated and invoked from another language targeting the CLR. That
language may invoke a method on a null instance.

Basically, the C# compiler always uses the CIL instruction 'callvirt'
for calling instance methods, even on non-virtual methods. Other
compilers may use 'call' rather than 'callvirt'.

There is a difference between using 'call' and 'callvirt': 'callvirt'
throws an exception if the instance is null, while 'call' doesn't.

---8<---
..assembly extern mscorlib {}
..assembly Test {}
..subsystem 0x0003

..class App extends [mscorlib]System.Object
{
.method public instance void Test()
{
ldstr "This is null\? {0}"

ldarg.0
ldnull
ceq
box [mscorlib]System.Boolean
call void [mscorlib]System.Console::WriteLine(string,object)
ret
}

.method public instance void .ctor()
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}

.method public static void Main()
{
.entrypoint

ldstr "First:"
call void [mscorlib]System.Console::WriteLine(string)
ldnull
call instance void App::Test()

ldstr "Second:"
call void [mscorlib]System.Console::WriteLine(string)
ldnull
callvirt instance void App::Test()
ret
}
}
--->8---

Compile with ilasm, and execute:

---8<---
First:
This is null? True
Second:

Unhandled Exception: System.NullReferenceException: Object reference not
set to an instance of an object.
at App.Main()
--->8---

-- Barry

--
http://barrkel.blogspot.com/
May 27 '06 #11
>Great. So we would always have to put if (this!=null) throw new
ArgumentNullException(); in every method just to make sure :-)


Personally I'm happy with the NullReferenceException that will be
thrown the first time I try to access a field.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
May 27 '06 #12
> Basically, the C# compiler always uses the CIL instruction 'callvirt'
for calling instance methods, even on non-virtual methods. Other
compilers may use 'call' rather than 'callvirt'.

There is a difference between using 'call' and 'callvirt': 'callvirt'
throws an exception if the instance is null, while 'call' doesn't.


wouldn't that mean that a method call in c# is slower than that one in other
languages due to the extra vtable lookup?
May 28 '06 #13
"cody" <de********@gmx.de> wrote:
Basically, the C# compiler always uses the CIL instruction 'callvirt'
for calling instance methods, even on non-virtual methods. Other
compilers may use 'call' rather than 'callvirt'.

There is a difference between using 'call' and 'callvirt': 'callvirt'
throws an exception if the instance is null, while 'call' doesn't.


wouldn't that mean that a method call in c# is slower than that one in other
languages due to the extra vtable lookup?


It's not looking up the vtable (non-virtual methods aren't in the
vtable), but it would be ever so slightly slower, yes.

-- Barry

--
http://barrkel.blogspot.com/
May 29 '06 #14
>> > Basically, the C# compiler always uses the CIL instruction 'callvirt'
> for calling instance methods, even on non-virtual methods. Other
> compilers may use 'call' rather than 'callvirt'.
>
> There is a difference between using 'call' and 'callvirt': 'callvirt'
> throws an exception if the instance is null, while 'call' doesn't.


wouldn't that mean that a method call in c# is slower than that one in
other
languages due to the extra vtable lookup?


It's not looking up the vtable (non-virtual methods aren't in the
vtable), but it would be ever so slightly slower, yes.


yes they aren't, but how can the instruction know wheather the method is a
virtual one or not without looking into the vtable or is this resolved at
jit time?
May 29 '06 #15
"cody" <de********@gmx.de> wrote:
It's not looking up the vtable (non-virtual methods aren't in the
vtable), but it would be ever so slightly slower, yes.
yes they aren't, but how can the instruction know wheather the method is a
virtual one or not without looking into the vtable or is this resolved at
jit time?


It is resolved at JIT time, by looking up the method information in
metadata. My investigation follows:

What's the difference in JIT-compiled code between 'call' and 'callvirt'
on CLR 2.0.50727?

I started with this CIL:

---8<---
..assembly extern mscorlib {}
..assembly Test {}
..subsystem 0x0003

..class App extends [mscorlib]System.Object
{
.method public instance void Test()
{
ldstr "This is null\? {0}"

ldarg.0
ldnull
ceq
box [mscorlib]System.Boolean
call void [mscorlib]System.Console::WriteLine(string,object)
ret
}

.method public static void Main()
{
.entrypoint

ldstr "First:"
call void [mscorlib]System.Console::WriteLine(string)
ldnull
call instance void App::Test()

ldstr "Second:"
call void [mscorlib]System.Console::WriteLine(string)
ldnull
callvirt instance void App::Test()
ret
}
}
--->8---

Roughly transliterated into C# code, it looks like this:

---8<---
using System;

class App
{
public void Test()
{
Console.WriteLine("This is null? {0}", this == null);
}

public static void Main()
{
Console.WriteLine("First:");
((App) null).Test(); // with 'call': not possible in MS C# 2.0
Console.WriteLine("Second:");
((App) null).Test(); // with 'callvirt': default for C# compiler
}
}
--->8---

This assembly's name is Test, but I compiled it to an executable called
CallVirt.exe, with ilasm, and started the VS 2005 debugger:

---8<---
ilasm -debug=opt CallVirt.il
devenv -debugexe CallVirt.exe
--->8---

I changed the project's debugger settings from Auto to Mixed, and
stepped into the code. When disassembled with SOS, the code for the
App.Main method looks like this:

---8<---
..load sos
extension C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos. dll loaded

!name2ee CallVirt.exe App.Main
PDB symbol for mscorwks.dll not loaded
Module: 00912c14 (CallVirt.exe)
Token: 0x06000002
MethodDesc: 00912fe0
Name: App.Main()
JITTED Code Address: 00de0070

!u 00de0070
Normal JIT generated code
App.Main()
Begin 00de0070, size 61
00DE0070 833D84102B0200 cmp dword ptr ds:[022B1084h],0 00DE0077 750A jne 00DE0083
00DE0079 B901000000 mov ecx,1
00DE007E E889D75678 call 7934D80C
(System.Console.InitializeStdOutError(Boolean), mdToken: 0600070f)
00DE0083 8B0D84102B02 mov ecx,dword ptr ds:[022B1084h]
00DE0089 8B153C302B02 mov edx,dword ptr ds:[022B303Ch]
00DE008F 8B01 mov eax,dword ptr [ecx]
00DE0091 FF90D8000000 call dword ptr [eax+000000D8h]
00DE0097 33C9 xor ecx,ecx
00DE0099 FF1520309100 call dword ptr ds:[00913020h]
00DE009F 833D84102B0200 cmp dword ptr ds:[022B1084h],0
00DE00A6 750A jne 00DE00B2
00DE00A8 B901000000 mov ecx,1
00DE00AD E85AD75678 call 7934D80C
(System.Console.InitializeStdOutError(Boolean), mdToken: 0600070f)
00DE00B2 8B0D84102B02 mov ecx,dword ptr ds:[022B1084h]
00DE00B8 8B1540302B02 mov edx,dword ptr ds:[022B3040h]
00DE00BE 8B01 mov eax,dword ptr [ecx]
00DE00C0 FF90D8000000 call dword ptr [eax+000000D8h]
00DE00C6 33C9 xor ecx,ecx
00DE00C8 3909 cmp dword ptr [ecx],ecx
00DE00CA FF1520309100 call dword ptr ds:[00913020h]
00DE00D0 C3 ret
--->8---

This code is longer that strictly "necessary" because the
Console::WriteLine(string) method has been inlined. The two relevant
snippets of code for 'call' and 'callvirt', including the setting of the
'this' argument to null, are as follows:

---8<---
// CALL
00DE0097 33C9 xor ecx,ecx
00DE0099 FF1520309100 call dword ptr ds:[00913020h]

// CALLVIRT
00DE00C6 33C9 xor ecx,ecx
00DE00C8 3909 cmp dword ptr [ecx],ecx
00DE00CA FF1520309100 call dword ptr ds:[00913020h]
--->8---

The difference with CALLVIRT is that it tests the pointer by
dereferencing it. That causes a hardware exception when the pointer is
null, and that hardware exception gets propagated to the CLR via Windows
SEH.

Something interesting that can be observed from this: the calls to the
App.Test() method are through an indirection. A peek in the address
shows the data:

---8<---d -format:fourbytes 0x00913020

0x00913020 00de00e8 00de0070 00000080 022b1ec4
0x00913030 912fd8b8 e9ed8900 ffa2eed0 912fe0b8
0x00913040 e9ed8900 ffa2eec4 576f62e8 cccc5e79
0x00913050 00912fe0 00000000 00000000 00000000
--->8---

One can then disassemble the code at the indirect location:

---8<---
!u 0x00de00e8

Normal JIT generated code
App.Test()
Begin 00de00e8, size 44 00DE00E8 57 push edi


.... etc.
--->8---

So, calls to non-virtual instance methods compiled with the current C#
compiler get turned into CIL 'callvirt' instructions, which, with the
current JIT compiler, test the 'this' argument with a CMP instruction.

-- Barry

--
http://barrkel.blogspot.com/
May 29 '06 #16
very interesting! thank you for this great info!

--
"Barry Kelly" <ba***********@gmail.com> schrieb im Newsbeitrag
news:ms********************************@4ax.com...
"cody" <de********@gmx.de> wrote:
> It's not looking up the vtable (non-virtual methods aren't in the
> vtable), but it would be ever so slightly slower, yes.


yes they aren't, but how can the instruction know wheather the method is
a
virtual one or not without looking into the vtable or is this resolved at
jit time?


It is resolved at JIT time, by looking up the method information in
metadata. My investigation follows:

What's the difference in JIT-compiled code between 'call' and 'callvirt'
on CLR 2.0.50727?

I started with this CIL:

---8<---
.assembly extern mscorlib {}
.assembly Test {}
.subsystem 0x0003

.class App extends [mscorlib]System.Object
{
.method public instance void Test()
{
ldstr "This is null\? {0}"

ldarg.0
ldnull
ceq
box [mscorlib]System.Boolean
call void [mscorlib]System.Console::WriteLine(string,object)
ret
}

.method public static void Main()
{
.entrypoint

ldstr "First:"
call void [mscorlib]System.Console::WriteLine(string)
ldnull
call instance void App::Test()

ldstr "Second:"
call void [mscorlib]System.Console::WriteLine(string)
ldnull
callvirt instance void App::Test()
ret
}
}
--->8---

Roughly transliterated into C# code, it looks like this:

---8<---
using System;

class App
{
public void Test()
{
Console.WriteLine("This is null? {0}", this == null);
}

public static void Main()
{
Console.WriteLine("First:");
((App) null).Test(); // with 'call': not possible in MS C# 2.0
Console.WriteLine("Second:");
((App) null).Test(); // with 'callvirt': default for C# compiler
}
}
--->8---

This assembly's name is Test, but I compiled it to an executable called
CallVirt.exe, with ilasm, and started the VS 2005 debugger:

---8<---
ilasm -debug=opt CallVirt.il
devenv -debugexe CallVirt.exe
--->8---

I changed the project's debugger settings from Auto to Mixed, and
stepped into the code. When disassembled with SOS, the code for the
App.Main method looks like this:

---8<---
.load sos
extension C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos. dll loaded

!name2ee CallVirt.exe App.Main
PDB symbol for mscorwks.dll not loaded
Module: 00912c14 (CallVirt.exe)
Token: 0x06000002
MethodDesc: 00912fe0
Name: App.Main()
JITTED Code Address: 00de0070

!u 00de0070
Normal JIT generated code
App.Main()
Begin 00de0070, size 61
00DE0070 833D84102B0200 cmp dword ptr ds:[022B1084h],0 00DE0077 750A jne 00DE0083
00DE0079 B901000000 mov ecx,1
00DE007E E889D75678 call 7934D80C
(System.Console.InitializeStdOutError(Boolean), mdToken: 0600070f)
00DE0083 8B0D84102B02 mov ecx,dword ptr ds:[022B1084h]
00DE0089 8B153C302B02 mov edx,dword ptr ds:[022B303Ch]
00DE008F 8B01 mov eax,dword ptr [ecx]
00DE0091 FF90D8000000 call dword ptr [eax+000000D8h]
00DE0097 33C9 xor ecx,ecx
00DE0099 FF1520309100 call dword ptr ds:[00913020h]
00DE009F 833D84102B0200 cmp dword ptr ds:[022B1084h],0
00DE00A6 750A jne 00DE00B2
00DE00A8 B901000000 mov ecx,1
00DE00AD E85AD75678 call 7934D80C
(System.Console.InitializeStdOutError(Boolean), mdToken: 0600070f)
00DE00B2 8B0D84102B02 mov ecx,dword ptr ds:[022B1084h]
00DE00B8 8B1540302B02 mov edx,dword ptr ds:[022B3040h]
00DE00BE 8B01 mov eax,dword ptr [ecx]
00DE00C0 FF90D8000000 call dword ptr [eax+000000D8h]
00DE00C6 33C9 xor ecx,ecx
00DE00C8 3909 cmp dword ptr [ecx],ecx
00DE00CA FF1520309100 call dword ptr ds:[00913020h]
00DE00D0 C3 ret
--->8---

This code is longer that strictly "necessary" because the
Console::WriteLine(string) method has been inlined. The two relevant
snippets of code for 'call' and 'callvirt', including the setting of the
'this' argument to null, are as follows:

---8<---
// CALL
00DE0097 33C9 xor ecx,ecx
00DE0099 FF1520309100 call dword ptr ds:[00913020h]

// CALLVIRT
00DE00C6 33C9 xor ecx,ecx
00DE00C8 3909 cmp dword ptr [ecx],ecx
00DE00CA FF1520309100 call dword ptr ds:[00913020h]
--->8---

The difference with CALLVIRT is that it tests the pointer by
dereferencing it. That causes a hardware exception when the pointer is
null, and that hardware exception gets propagated to the CLR via Windows
SEH.

Something interesting that can be observed from this: the calls to the
App.Test() method are through an indirection. A peek in the address
shows the data:

---8<---
d -format:fourbytes 0x00913020

0x00913020 00de00e8 00de0070 00000080 022b1ec4
0x00913030 912fd8b8 e9ed8900 ffa2eed0 912fe0b8
0x00913040 e9ed8900 ffa2eec4 576f62e8 cccc5e79
0x00913050 00912fe0 00000000 00000000 00000000
--->8---

One can then disassemble the code at the indirect location:

---8<---
!u 0x00de00e8

Normal JIT generated code
App.Test()
Begin 00de00e8, size 44 00DE00E8 57 push edi


... etc.
--->8---

So, calls to non-virtual instance methods compiled with the current C#
compiler get turned into CIL 'callvirt' instructions, which, with the
current JIT compiler, test the 'this' argument with a CMP instruction.

-- Barry

--
http://barrkel.blogspot.com/

May 29 '06 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Prakash | last post by:
Hi, I want to generate the JDK API using Javadoc. I have installed java 1.4.2 in WINDOWS. Since i don't have frequent access to the Net, i want to generate the Java API Help using javadoc.But I...
43
by: Anitha | last post by:
Hi I observed something while coding the other day: if I declare a character array as char s, and try to use it as any other character array..it works perfectly fine most of the times. It...
29
by: junky_fellow | last post by:
Consider the following piece of code: struct junk { int i_val; int i_val1; char c_val; }; int main(void) {
40
by: Dave Hansen | last post by:
Please note crosspost. Often when writing code requiring function pointers, it is necessary to write functions that ignore their formal parameters. For example, a state machine function might...
1
by: billa1972 | last post by:
Hi, I am trying to hook into Yellow Freight's rating webservice. Below is the wsdl. When i try and create a proxy file with wsdl.exe i get the following errors, see below. Also, when i...
5
by: Peter Ritchie [C# MVP] | last post by:
I've purposely been ignoring a CA2122 warning in some C++ interop code I've been working on for quite some time. I've just recently had the cycles to investigate the warning. The warning message...
2
by: BSeab1024SE | last post by:
In MS Visual C++ some code I wrote generated the warning "conversion from 'int' to 'const float', possible loss of data." In the process of trying to determine if I could rewrite the code to...
82
by: robert bristow-johnson | last post by:
here is a post i put out (using Google Groups) that got dropped by google: i am using gcc as so: $ gcc -v Using built-in specs. Target: i386-redhat-linux Configured with: ../configure...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.