.NET Framework 4の互換性の問題

15750 ワード

テストプログラム


次の非常に簡単なCプログラムTesterを見てみましょう.cs:
 1 using System;

 2 

 3 static class Tester

 4 {

 5   static void Main()

 6   {

 7     Console.WriteLine("   CLR: " + Environment.Version);

 8     Console.WriteLine("Concat: " + string.Concat(new int[]{12, 345}));

 9   }

10 }

このテストプログラムの実質的な内容は1行だけで,8行目でstringクラスの静的メソッドConcatを呼び出した.

実行結果


上記のテストプログラムの実行結果を見てみましょう.まずLinuxオペレーティングシステムのMono環境です.
ben@vbox:~/work> gmcs Tester.cs && mono Tester.exe

   CLR: 2.0.50727.1433

Concat: System.Int32[]

ben@vbox:~/work> dmcs Tester.cs && mono Tester.exe

   CLR: 4.0.30319.1

Concat: 12345


WindowsオペレーティングシステムのMicrosoftもあります.NET Framework環境:
D:\work> C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe Tester.cs

Microsoft (R) Visual C# 2005     8.00.50727.4016

  Microsoft (R) Windows (R) 2005 Framework   2.0.50727

 (C) Microsoft Corporation 2001-2005。 。



D:\work> Tester.exe

   CLR: 2.0.50727.4216

Concat: System.Int32[]



D:\work> C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe Tester.cs

Microsoft(R) Visual C# 2010   4.0.30319.1  

 (C) Microsoft Corporation。 。



D:\work> Tester.exe

   CLR: 4.0.30319.276

Concat: 12345


同じC#プログラムで、LinuxオペレーティングシステムでもWindowsオペレーティングシステムでも、NET Framework 2.0と.NET Framework 4の間には互換性がないことが示されている.

ぶんせき


上記の運転結果は、主にstring類の静的方法Concatがあるためである.NET Framework 2.0には9種類のリロードバージョンがあります.NET Framework 4には11種類のリロードバージョンがあります.上記テスト用のC#プログラムで実際に呼び出されたリロードバージョンは以下の通りです.
.NET Framework 2.0: public static string Concat(Object arg0)

.NET Framework 4  : public static string Concat<T>(IEnumerable<T> values)


どうやらNET Framework Base Class Libraryで新しい方法を追加するのも安全ではなく、既存のC#プログラムの動作を変える可能性があります.これは私たちに既存のプログラムをNET Framework 2.0行き.NET Framework 4の移行には注意が必要です.MSDNで「バージョン注意事項」が明確に指摘されている点だけでなく、微妙な変更にも注意してください.

ILコードの表示


Linuxオペレーティングシステムの下で次のコマンドを実行してTesterを逆アセンブリします.ExceはILASMソースファイル:
ben@vbox:~/work> gmcs Tester.cs && monodis Tester.exe > Tester-v2.il

ben@vbox:~/work> dmcs Tester.cs && monodis Tester.exe > Tester-v4.il


次はTester-v 2です.ilファイル:
 1 .assembly extern mscorlib

 2 {

 3   .ver 2:0:0:0

 4   .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..

 5 }

 6 .assembly 'Tester'

 7 {

 8   .custom instance void class [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::'.ctor'() =  (

 9                 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx

10                 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01       ) // ceptionThrows.

11 

12   .hash algorithm 0x00008004

13   .ver  0:0:0:0

14 }

15 .module Tester.exe // GUID = {9F6A8C8F-B962-4E6A-A4E9-FA6FF9E83982}

16 

17 

18   .class private auto ansi abstract sealed beforefieldinit Tester

19         extends [mscorlib]System.Object

20   {

21 

22     // method line 1

23     .method private static hidebysig

24            default void Main ()  cil managed

25     {

26         // Method begins at RVA 0x20ec

27         .entrypoint

28         // Code size 60 (0x3c)

29         .maxstack 8

30         IL_0000:  ldstr "   CLR: "

31         IL_0005:  call class [mscorlib]System.Version class [mscorlib]System.Environment::get_Version()

32         IL_000a:  call string string::Concat(object, object)

33         IL_000f:  call void class [mscorlib]System.Console::WriteLine(string)

34         IL_0014:  ldstr "Concat: "

35         IL_0019:  ldc.i4.2

36         IL_001a:  newarr [mscorlib]System.Int32

37         IL_001f:  dup

38         IL_0020:  ldc.i4.0

39         IL_0021:  ldc.i4.s 0x0c

40         IL_0023:  stelem.i4

41         IL_0024:  dup

42         IL_0025:  ldc.i4.1

43         IL_0026:  ldc.i4 345

44         IL_002b:  stelem.i4

45         IL_002c:  call string string::Concat(object)

46         IL_0031:  call string string::Concat(string, string)

47         IL_0036:  call void class [mscorlib]System.Console::WriteLine(string)

48         IL_003b:  ret

49     } // end of method Tester::Main

50 

51   } // end of class Tester

さらにdiffコマンドを使用してTester-v 4を見てみましょう.ilとTester-v 2.ilの違い:
ben@vbox:~/work> diff Tester-v2.il Tester-v4.il

3c3

<   .ver 2:0:0:0

---

>   .ver 4:0:0:0

15c15

< .module Tester.exe // GUID = {9F6A8C8F-B962-4E6A-A4E9-FA6FF9E83982}

---

> .module Tester.exe // GUID = {D564CE72-73D3-43DD-B6F4-FB12809D5589}

45c45

<       IL_002c:  call string string::Concat(object)

---

>       IL_002c:  call string string::Concat<int32> (class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)


全部で3つの違いしかありません.
  • の3行目の違いは異なることを説明する.NET Frameworkバージョン.
  • の15行目の違いは異なるTesterを説明しただけだ.exeのGUIDが違います.
  • の45行目の違いは、呼び出されたConcatメソッドのリロードバージョンが異なることを示している.

  • 上記の3点目の違いは、前節の分析を検証し、対応する呼び出しのConcatメソッドの異なるリロードバージョンを明確に示しています.

    参考資料

  • MSDN: String.Concatメソッド(System)
  • MSDN: String.Concatメソッド(Object)(System)
  • MSDN: String.Concat(T)メソッド(IEnumerable(T))(System)