Why is !0 a type in Microsoft Intermediate Language (MSIL)?












86















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?










share|improve this question





























    86















    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?










    share|improve this question



























      86












      86








      86


      2






      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?










      share|improve this question
















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jul 22 '15 at 11:02









      DSF

      1,45452655




      1,45452655










      asked Jul 22 '15 at 9:59









      DragnoDragno

      1,3391727




      1,3391727
























          2 Answers
          2






          active

          oldest

          votes


















          114














          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.






          share|improve this answer

































            35














            That is a generic type parameter.



            They are positional.



            Decompile some generic code to see how they are used (compare IL vs C#).






            share|improve this answer



















            • 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











            • @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













            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
            });


            }
            });














            draft saved

            draft discarded


















            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









            114














            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.






            share|improve this answer






























              114














              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.






              share|improve this answer




























                114












                114








                114







                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.






                share|improve this answer















                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.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jul 29 '15 at 10:57

























                answered Jul 22 '15 at 10:37









                Hans PassantHans Passant

                794k10913172103




                794k10913172103

























                    35














                    That is a generic type parameter.



                    They are positional.



                    Decompile some generic code to see how they are used (compare IL vs C#).






                    share|improve this answer



















                    • 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











                    • @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


















                    35














                    That is a generic type parameter.



                    They are positional.



                    Decompile some generic code to see how they are used (compare IL vs C#).






                    share|improve this answer



















                    • 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











                    • @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
















                    35












                    35








                    35







                    That is a generic type parameter.



                    They are positional.



                    Decompile some generic code to see how they are used (compare IL vs C#).






                    share|improve this answer













                    That is a generic type parameter.



                    They are positional.



                    Decompile some generic code to see how they are used (compare IL vs C#).







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    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 !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
















                    • 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











                    • @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










                    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




















                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    Mossoró

                    Error while reading .h5 file using the rhdf5 package in R

                    Pushsharp Apns notification error: 'InvalidToken'