Why is !0 a type in Microsoft Intermediate Language (MSIL)?
In many MSIL listings, I have observed the following:
System.Nullable`1<!0> etc ...
or
class !0 etc ...
What's the meaning of !0 in these circumstances?
c# .net cil
add a comment |
In many MSIL listings, I have observed the following:
System.Nullable`1<!0> etc ...
or
class !0 etc ...
What's the meaning of !0 in these circumstances?
c# .net cil
add a comment |
In many MSIL listings, I have observed the following:
System.Nullable`1<!0> etc ...
or
class !0 etc ...
What's the meaning of !0 in these circumstances?
c# .net cil
In many MSIL listings, I have observed the following:
System.Nullable`1<!0> etc ...
or
class !0 etc ...
What's the meaning of !0 in these circumstances?
c# .net cil
c# .net cil
edited Jul 22 '15 at 11:02
DSF
1,45452655
1,45452655
asked Jul 22 '15 at 9:59
DragnoDragno
1,3391727
1,3391727
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
This is quirk of the decompiler you use to look at a .NET assembly. It is the behavior of ildasm.exe, other ones like Reflector or ILSpy get this right. The Microsoft programmer who wrote it took a shortcut, he generates a string from the IL that just displays the type argument the way it is encoded, without writing the extra code to lookup the type argument name in the metadata.
You need to read !n as the n-th type argument of the generic type. Where !0 means "first type argument", !1 means "second type argument", etcetera. For Nullable<>, you know that '!0` means 'T' from the MSDN article.
You may also encounter something like !!T. Two exclamation marks indicate a type argument for a generic method. This time, ildasm.exe does look up the type argument name instead of using !!0. Why the programmer took the shortcut on generic types but not on generic methods is hard to reverse-engineer. Ildasm is a pretty quirky program and is written in a C++ coding style that's very different from other C++ code in .NET. Not as disciplined, non-zero odds that this was an intern's assignment :)
The `1 suffix on "Nullable" is a normal encoding for generic type names, it indicates the generic type has one type argument. In other words, for Nullable<> you'll never see !1 being used.
So simply read !0 as "T". Or use a better decompiler.
add a comment |
That is a generic type parameter.
They are positional.
Decompile some generic code to see how they are used (compare IL vs C#).
4
If I use TryRoslyn I don't get it... goo.gl/ZZKE38 I get!Tand!!T, depending if the generic parameter is of the containing class or of the method... The same if I use ildasm
– xanatos
Jul 22 '15 at 12:17
@xanatos Not always. I also see code likeldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionaryorcall instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool). The raw IL only uses the positional argument anyway, though - the!TKeyis already an attempt to make the IL more readable. Maybe it doesn't always work well? The ECMA spec always uses the positional!0/!00as well.
– Luaan
Jul 22 '15 at 14:29
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f31559861%2fwhy-is-0-a-type-in-microsoft-intermediate-language-msil%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
This is quirk of the decompiler you use to look at a .NET assembly. It is the behavior of ildasm.exe, other ones like Reflector or ILSpy get this right. The Microsoft programmer who wrote it took a shortcut, he generates a string from the IL that just displays the type argument the way it is encoded, without writing the extra code to lookup the type argument name in the metadata.
You need to read !n as the n-th type argument of the generic type. Where !0 means "first type argument", !1 means "second type argument", etcetera. For Nullable<>, you know that '!0` means 'T' from the MSDN article.
You may also encounter something like !!T. Two exclamation marks indicate a type argument for a generic method. This time, ildasm.exe does look up the type argument name instead of using !!0. Why the programmer took the shortcut on generic types but not on generic methods is hard to reverse-engineer. Ildasm is a pretty quirky program and is written in a C++ coding style that's very different from other C++ code in .NET. Not as disciplined, non-zero odds that this was an intern's assignment :)
The `1 suffix on "Nullable" is a normal encoding for generic type names, it indicates the generic type has one type argument. In other words, for Nullable<> you'll never see !1 being used.
So simply read !0 as "T". Or use a better decompiler.
add a comment |
This is quirk of the decompiler you use to look at a .NET assembly. It is the behavior of ildasm.exe, other ones like Reflector or ILSpy get this right. The Microsoft programmer who wrote it took a shortcut, he generates a string from the IL that just displays the type argument the way it is encoded, without writing the extra code to lookup the type argument name in the metadata.
You need to read !n as the n-th type argument of the generic type. Where !0 means "first type argument", !1 means "second type argument", etcetera. For Nullable<>, you know that '!0` means 'T' from the MSDN article.
You may also encounter something like !!T. Two exclamation marks indicate a type argument for a generic method. This time, ildasm.exe does look up the type argument name instead of using !!0. Why the programmer took the shortcut on generic types but not on generic methods is hard to reverse-engineer. Ildasm is a pretty quirky program and is written in a C++ coding style that's very different from other C++ code in .NET. Not as disciplined, non-zero odds that this was an intern's assignment :)
The `1 suffix on "Nullable" is a normal encoding for generic type names, it indicates the generic type has one type argument. In other words, for Nullable<> you'll never see !1 being used.
So simply read !0 as "T". Or use a better decompiler.
add a comment |
This is quirk of the decompiler you use to look at a .NET assembly. It is the behavior of ildasm.exe, other ones like Reflector or ILSpy get this right. The Microsoft programmer who wrote it took a shortcut, he generates a string from the IL that just displays the type argument the way it is encoded, without writing the extra code to lookup the type argument name in the metadata.
You need to read !n as the n-th type argument of the generic type. Where !0 means "first type argument", !1 means "second type argument", etcetera. For Nullable<>, you know that '!0` means 'T' from the MSDN article.
You may also encounter something like !!T. Two exclamation marks indicate a type argument for a generic method. This time, ildasm.exe does look up the type argument name instead of using !!0. Why the programmer took the shortcut on generic types but not on generic methods is hard to reverse-engineer. Ildasm is a pretty quirky program and is written in a C++ coding style that's very different from other C++ code in .NET. Not as disciplined, non-zero odds that this was an intern's assignment :)
The `1 suffix on "Nullable" is a normal encoding for generic type names, it indicates the generic type has one type argument. In other words, for Nullable<> you'll never see !1 being used.
So simply read !0 as "T". Or use a better decompiler.
This is quirk of the decompiler you use to look at a .NET assembly. It is the behavior of ildasm.exe, other ones like Reflector or ILSpy get this right. The Microsoft programmer who wrote it took a shortcut, he generates a string from the IL that just displays the type argument the way it is encoded, without writing the extra code to lookup the type argument name in the metadata.
You need to read !n as the n-th type argument of the generic type. Where !0 means "first type argument", !1 means "second type argument", etcetera. For Nullable<>, you know that '!0` means 'T' from the MSDN article.
You may also encounter something like !!T. Two exclamation marks indicate a type argument for a generic method. This time, ildasm.exe does look up the type argument name instead of using !!0. Why the programmer took the shortcut on generic types but not on generic methods is hard to reverse-engineer. Ildasm is a pretty quirky program and is written in a C++ coding style that's very different from other C++ code in .NET. Not as disciplined, non-zero odds that this was an intern's assignment :)
The `1 suffix on "Nullable" is a normal encoding for generic type names, it indicates the generic type has one type argument. In other words, for Nullable<> you'll never see !1 being used.
So simply read !0 as "T". Or use a better decompiler.
edited Jul 29 '15 at 10:57
answered Jul 22 '15 at 10:37
Hans PassantHans Passant
794k10913172103
794k10913172103
add a comment |
add a comment |
That is a generic type parameter.
They are positional.
Decompile some generic code to see how they are used (compare IL vs C#).
4
If I use TryRoslyn I don't get it... goo.gl/ZZKE38 I get!Tand!!T, depending if the generic parameter is of the containing class or of the method... The same if I use ildasm
– xanatos
Jul 22 '15 at 12:17
@xanatos Not always. I also see code likeldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionaryorcall instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool). The raw IL only uses the positional argument anyway, though - the!TKeyis already an attempt to make the IL more readable. Maybe it doesn't always work well? The ECMA spec always uses the positional!0/!00as well.
– Luaan
Jul 22 '15 at 14:29
add a comment |
That is a generic type parameter.
They are positional.
Decompile some generic code to see how they are used (compare IL vs C#).
4
If I use TryRoslyn I don't get it... goo.gl/ZZKE38 I get!Tand!!T, depending if the generic parameter is of the containing class or of the method... The same if I use ildasm
– xanatos
Jul 22 '15 at 12:17
@xanatos Not always. I also see code likeldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionaryorcall instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool). The raw IL only uses the positional argument anyway, though - the!TKeyis already an attempt to make the IL more readable. Maybe it doesn't always work well? The ECMA spec always uses the positional!0/!00as well.
– Luaan
Jul 22 '15 at 14:29
add a comment |
That is a generic type parameter.
They are positional.
Decompile some generic code to see how they are used (compare IL vs C#).
That is a generic type parameter.
They are positional.
Decompile some generic code to see how they are used (compare IL vs C#).
answered Jul 22 '15 at 10:01
leppieleppie
98k16168275
98k16168275
4
If I use TryRoslyn I don't get it... goo.gl/ZZKE38 I get!Tand!!T, depending if the generic parameter is of the containing class or of the method... The same if I use ildasm
– xanatos
Jul 22 '15 at 12:17
@xanatos Not always. I also see code likeldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionaryorcall instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool). The raw IL only uses the positional argument anyway, though - the!TKeyis already an attempt to make the IL more readable. Maybe it doesn't always work well? The ECMA spec always uses the positional!0/!00as well.
– Luaan
Jul 22 '15 at 14:29
add a comment |
4
If I use TryRoslyn I don't get it... goo.gl/ZZKE38 I get!Tand!!T, depending if the generic parameter is of the containing class or of the method... The same if I use ildasm
– xanatos
Jul 22 '15 at 12:17
@xanatos Not always. I also see code likeldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionaryorcall instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool). The raw IL only uses the positional argument anyway, though - the!TKeyis already an attempt to make the IL more readable. Maybe it doesn't always work well? The ECMA spec always uses the positional!0/!00as well.
– Luaan
Jul 22 '15 at 14:29
4
4
If I use TryRoslyn I don't get it... goo.gl/ZZKE38 I get
!T and !!T, depending if the generic parameter is of the containing class or of the method... The same if I use ildasm– xanatos
Jul 22 '15 at 12:17
If I use TryRoslyn I don't get it... goo.gl/ZZKE38 I get
!T and !!T, depending if the generic parameter is of the containing class or of the method... The same if I use ildasm– xanatos
Jul 22 '15 at 12:17
@xanatos Not always. I also see code like
ldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionary or call instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool). The raw IL only uses the positional argument anyway, though - the !TKey is already an attempt to make the IL more readable. Maybe it doesn't always work well? The ECMA spec always uses the positional !0/!00 as well.– Luaan
Jul 22 '15 at 14:29
@xanatos Not always. I also see code like
ldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionary or call instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool). The raw IL only uses the positional argument anyway, though - the !TKey is already an attempt to make the IL more readable. Maybe it doesn't always work well? The ECMA spec always uses the positional !0/!00 as well.– Luaan
Jul 22 '15 at 14:29
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f31559861%2fwhy-is-0-a-type-in-microsoft-intermediate-language-msil%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown