Shouldn't if (this!=null) generate a compiler warning?
in fact, it does not. 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
"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... :-)
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
"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)
:-)
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
"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..."
>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.
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.
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...
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/
>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.
> 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?
"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/
>> > 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?
"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/
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/ This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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...
|
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)
{
|
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...
|
by: Adam P |
last post by:
Is there anyway to do this?
|
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...
|
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...
|
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...
|
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...
|
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...
|
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...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
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...
|
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...
|
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...
|
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,...
|
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...
|
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,...
| |