<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【.NET】利用 IL 魔法實現(xiàn)隨心隨意的泛型約束

      眾所周知,C# 只支持對 基類/接口/class/struct/new() 以及一些 IDE 魔法的約束,比如這樣

      public static string Test<T>(T value) where T : ITest
      {
          return value.Test();
      }
      
      public interface ITest
      {
          string Test();
      }

      但是如果我們想要隨心所欲的約束就不行了

      public static string Test<T>(T value) where T : { string Test(); }
      {
          return value.Test();
      }

      最近無聊亂折騰 MSIL,弄出來好多不能跑的魔法,雖然不能跑但是反編譯出的 C# 看著很神奇,其中正好就有想看看能不能弄個神奇的泛型出來,于是我胡寫了一段代碼

      .assembly _
      {
      }
      
      .class public Test
      {
          .method public void .ctor()
          {
              ldarg.0
              call instance void object::.ctor()
              ret
          }
      
          .method public static void Main()
          {
              .entrypoint
              newobj instance void Test::.ctor()
              call string Test::Test<class Test>(!!0)
              call void [mscorlib]System.Console::WriteLine(string)
              ret
          }
      
          .method public static string Test<T>(!!T t)
          {
              ldarg.s t
              callvirt instance string !!T::Test()
              ret
          }
      
          .method public string Test()
          {
              ldstr "Call instance string Test::Test()"
              ret
          }
      }

      反編譯出來是這樣的

      public class Test
      {
          public static void Main()
          {
              Console.WriteLine(Test(new Test()));
          }
      
          public unsafe static string Test<T>(T t)
          {
              return ((T*)t)->Test();
          }
      
          public string Test()
          {
              return "Call instance string Test::Test()";
          }
      }

      這段代碼是無法運行的,在 .NET Framework 會直接無返回,而在 Mono 會報錯

      [ERROR] FATAL UNHANDLED EXCEPTION: System.MissingMethodException: Method not found: string .T_REF.Test()
          at Test.Main () [0x00005] in <ddf64a5d94ef4722be4197eb692d9478>:0

      于是我就當這是 .NET 泛型的局限性了,后來有群友提醒我說約束會影響運行時,于是我就嘗試加上約束

      .method public static string Test<(Test) T>(!!T t)
      {
          ldarg.s t
          callvirt instance string !!T::Test()
          ret
      }

      發(fā)現(xiàn)真的能跑了(Framework 依然無返回。。。),于是我就看看能不能同時約束兩個類型

      .method public static string Test<(Test, Test2) T>(!!T t)
      {
          ldarg.s t
          callvirt instance string !!T::Test()
          ret
      }

      Mono 成功輸出

      Call instance string Test::Test()
      Call instance string Test2::Test()

      而 Framework 直接運行時約束了。。。

      未經(jīng)處理的異常: System.Security.VerificationException: 方法 Test.Test: 類型參數(shù)“Test”與類型參數(shù)“T”的約束沖突。
          在 Test.Main()

      很明顯 Mono 給泛型開了洞

      隨后測試發(fā)現(xiàn),只要約束的類有相關(guān)成員就可以正常調(diào)用,于是我就利用抽象類做接口

      .assembly _
      {
      }
      
      .class public Test
      {
          .field string Test
      
          .method public void .ctor()
          {
              ldarg.0
              ldstr "This is Test"
              stfld string Test::Test
              ldarg.0
              call instance void object::.ctor()
              ret
          }
      
          .method public static void Main()
          {
              .entrypoint
              .locals init (
                  class Test test,
                  class Test2 test2
              )
              newobj instance void Test::.ctor()
              stloc.s test
              ldloc.s test
              call void Test::Test<class Test>(!!0)
              ldloc.s test
              call string Test::Test<class Test>(!!0)
              call void [mscorlib]System.Console::WriteLine(string)
              newobj instance void Test2::.ctor()
              stloc.s test2
              ldloc.s test2
              call void Test::Test<class Test2>(!!0)
              ldloc.s test2
              call string Test::Test<class Test2>(!!0)
              call void [mscorlib]System.Console::WriteLine(string)
              ret
          }
      
          .method public static void Test<(WithTest) T>(!!T t)
          {
              ldarg.s t
              ldfld string !!T::Test
              call void [mscorlib]System.Console::WriteLine(string)
              ret
          }
      
          .method public static string Test<(WithTest) T>(!!T t)
          {
              ldarg.s t
              callvirt instance string !!T::Test()
              ret
          }
      
          .method public string Test()
          {
              ldstr "Call instance string Test::Test()"
              ret
          }
      }
      
      .class public Test2
      {
          .field string Test
      
          .method public void .ctor()
          {
              ldarg.0
              ldstr "This is Test2"
              stfld string Test2::Test
              ldarg.0
              call instance void object::.ctor()
              ret
          }
      
          .method public newslot virtual string Test()
          {
              ldstr "Call instance string Test2::Test()"
              ret
          }
      }
      
      .class public abstract WithTest
      {
          .field string Test
      
          .method public newslot abstract virtual string Test()
          {
          }
      }

      正確輸出

      This is Test
      Call instance string Test::Test()
      This is Test2
      Call instance string Test2::Test()

      Framework 自然還是炸的

      最后反編譯出來長這樣

      public class Test
      {
          private string m_Test = "This is Test";
      
          public static void Main()
          {
              Test t = new Test();
              global::Test.Test<Test>(t);
              Console.WriteLine(global::Test.Test<Test>(t));
              Test2 t2 = new Test2();
              global::Test.Test<Test2>(t2);
              Console.WriteLine(global::Test.Test<Test2>(t2));
          }
      
          public unsafe static void Test<T>(T t) where T : WithTest
          {
              Console.WriteLine(((T*)t)->Test);
          }
      
          public unsafe static string Test<T>(T t) where T : WithTest
          {
              return ((T*)t)->Test();
          }
      
          public string Test()
          {
              return "Call instance string Test::Test()";
          }
      }
      
      public class Test2
      {
          private string m_Test = "This is Test2";
      
          public virtual string Test()
          {
              return "Call instance string Test2::Test()";
          }
      }
      
      public abstract class WithTest
      {
          private string m_Test;
      
          public abstract string Test();
      }

      當然,這種操作僅限娛樂,經(jīng)測試 .NET Framework 和 .NET Core App 都會卡在約束,所以 .NET 是別想有隨意的約束了,不過 C# 題案 "Roles and extensions" 倒是給出了曲線實現(xiàn)方案

      posted @ 2024-04-17 17:10  where-where  閱讀(154)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 久久经精品久久精品免费观看| 久久96热在精品国产高清| 成人午夜福利一区二区四区| 亚洲伊人久久综合影院| 抚州市| 久久精品国产91精品亚洲| 日本一道一区二区视频| 精品欧美一区二区三区久久久 | 国产区图片区小说区亚洲区| 中文字幕乱妇无码AV在线| 国产国产精品人体在线视| 狠狠噜天天噜日日噜| 任我爽精品视频在线播放| 亚洲天堂一区二区成人在线| 在线免费不卡视频| 国产色无码专区在线观看| 日本夜爽爽一区二区三区| 日本高清色WWW在线安全| 国产明星精品无码AV换脸| 国产av人人夜夜澡人人爽麻豆| 亚洲欧美日韩愉拍自拍美利坚| 在线天堂最新版资源| 日本一高清二区视频久二区| 日韩av第一页在线播放| 少妇撒尿一区二区在线视频| 国产精品中文字幕观看| 国产成人无码A区在线观看视频| 白丝乳交内射一二三区| 国产视频有码字幕一区二区| 亚洲人成网线在线播放VA| 国产女精品视频网站免费| 亚洲精品成人老司机影视| 精品一日韩美女性夜视频| 一区二区三区无码免费看| 亚洲中文字幕伊人久久无码| 久久人妻国产精品| 欧美日韩欧美| 国产一区二区三区国产视频| 国产精品白浆在线观看免费| 南召县| 狠狠综合久久av一区二|