このドキュメントは対象とするMonoのバージョンが古くなっています。 より新しいバージョンについては以下のページを参照してください。


ここでは、同じソースコードをコンパイルした物を、RedHat Linux 9上のMono 1.0とWindows XP上の.NET Framework version 1.1とで動作させた場合の結果の相違について考察します。 それぞれ、対象となる各名前空間に存在する基本的なクラスを用いて簡単な動作をさせています。 また、一方で生成したアセンブリが他方でも動作するかもテストします。 コンパイラにはmcsおよび.NET Framework version 1.1のcscを使用しました。

§1 System名前空間

System名前空間に存在するクラスを利用してみます。

using System;

namespace SamtaMarta.Samples.Mono.Compatibility
{
    class System
    {
        static void Main(string[] args)
        {
            // 簡単な入出力
            Console.WriteLine( "Hello world!" );

            int a, b;

            Console.Write( "a = ? " );

            a = Int32.Parse( Console.ReadLine().Trim() );
 
            Console.Write( "b = ? " );

            b = Int32.Parse( Console.ReadLine().Trim() );

            Console.WriteLine( "{0}+{1}={2}", a, b, a + b );
            Console.WriteLine( "{0}-{1}={2}", a, b, a - b );
            Console.WriteLine( "{0}*{1}={2}", a, b, a * b );
            Console.WriteLine( "{0}/{1}={2}", a, b, a / b );
            Console.WriteLine();

            // Environmentクラス
            Console.WriteLine( "OSVersion: {0} {1}", Environment.OSVersion.Platform, Environment.OSVersion.Version );
            Console.WriteLine( "CurrentDirectory: {0}", Environment.CurrentDirectory );
            Console.WriteLine( "SystemDirectory: {0}", Environment.SystemDirectory );
            Console.WriteLine( "UserName: {0}", Environment.UserName );
            Console.WriteLine( "MachineName: {0}", Environment.MachineName );
            Console.WriteLine();

            // Mathクラス
            Console.WriteLine( "Sin(π/2) = {0}", Math.Sin( Math.PI / 2.0 ) );
            Console.WriteLine( "Cos(π/3) = {0}", Math.Cos( Math.PI / 3.0 ) );
            Console.WriteLine( "e^2 = {0}", Math.Pow( Math.E, 2.0 ) );
            Console.WriteLine();

            // Randomクラス
            Random rand = new Random( 0 );

            Console.WriteLine( rand.Next() );
            Console.WriteLine( rand.Next() );
            Console.WriteLine( rand.Next() );
            Console.WriteLine();

            // DateTime構造体
            Console.WriteLine( "Now:    {0}", DateTime.Now );
            Console.WriteLine( "UtcNow: {0}", DateTime.UtcNow );
        }
    }
}
Monoでの実行結果
Hello world!
a = ? 6
b = ? 2
6+2=8
6-2=4
6*2=12
6/2=3

OSVersion: 128 2.4.20.31
CurrentDirectory: /home/santamarta/programming_cs/MonoCompatibility/System
SystemDirectory: 
UserName: santamarta
MachineName: localhost.localdomain

Sin(π/2) = 1
Cos(π/3) = 0.5
e^2 = 7.38905609893065

1559595546
1755192844
1649316166

Now:    2004/07/25 2:03:01
UtcNow: 2004/07/24 17:03:01
.NET Frameworkでの実行結果
Hello world!
a = ? 6
b = ? 2
6+2=8
6-2=4
6*2=12
6/2=3

OSVersion: Win32NT 5.1.2600.0
CurrentDirectory: D:\Temporaly\MonoCompatibility
SystemDirectory: C:\WINDOWS\System32
UserName: santa marta
MachineName: AYAYA

Sin(π/2) = 1
Cos(π/3) = 0.5
e^2 = 7.38905609893065

1559595546
1755192844
1649316166

Now:    2004/07/25 15:35:29
UtcNow: 2004/07/25 6:35:29
  • cscでコンパイルしたアセンブリ、RedHat Linux上のMonoで動作OK
  • mcsでコンパイルしたアセンブリ、Windows XP上の.NET Frameworkで動作OK

結果について見てみます。 OSのバージョンやシステムディレクトリなど、システムに依存する部分の結果は異なっています。 OSのバージョンについては、 Monoではカーネルのバージョンが表示されています。 また、乱数については同じシード値を用いていて全く同じ結果が出力されていることから、同じ乱数生成アルゴリズムが使われていると考えられます。

§2 System.Collections名前空間

次にSystem.Collections名前空間に存在するクラスを利用してみます。

using System;
using System.Collections;

namespace SamtaMarta.Samples.Mono.Compatibility
{
    class SystemCollections
    {
        static void Main(string[] args)
        {
            // ArrayList
            ArrayList arr = new ArrayList();

            arr.Add( "a" );
            arr.Add( "c" );
            arr.Add( "d" );
            arr.Add( "e" );
            arr.Add( "g" );
            arr.Add( "b" );
            arr.Add( "f" );

            foreach ( string str in arr )
            {
                Console.Write( "{0} ", str );
            }

            Console.WriteLine();

            arr.Sort();

            foreach ( string str in arr )
            {
                Console.Write( "{0} ", str );
            }

            Console.WriteLine();
            
            Console.WriteLine();

            // Stack
            Stack s = new Stack();

            Console.Write( "Pushed: " );

            for ( int i = 0; i < 10; i++ )
            {
                s.Push( i );

                Console.Write( "{0} ", i );
            }

            Console.WriteLine();

            Console.Write( "Popped: " );

            while ( 0 < s.Count )
            {
                Console.Write( "{0} ", (int)s.Pop() );
            }

            Console.WriteLine();

            Console.WriteLine();

            // Queue
            Queue q = new Queue();

            Console.Write( "Enqueued: " );

            for ( int i = 0; i < 10; i++ )
            {
                q.Enqueue( i );

                Console.Write( "{0} ", i );
            }

            Console.WriteLine();

            Console.Write( "Dequeued: " );

            while ( 0 < q.Count )
            {
                Console.Write( "{0} ", (int)q.Dequeue() );
            }

            Console.WriteLine();
        }
    }
}
Monoでの実行結果
a c d e g b f 
a b c d e f g 

Pushed: 0 1 2 3 4 5 6 7 8 9 
Popped: 9 8 7 6 5 4 3 2 1 0 

Enqueued: 0 1 2 3 4 5 6 7 8 9 
Dequeued: 0 1 2 3 4 5 6 7 8 9 
.NET Frameworkでの実行結果
a c d e g b f 
a b c d e f g 

Pushed: 0 1 2 3 4 5 6 7 8 9 
Popped: 9 8 7 6 5 4 3 2 1 0 

Enqueued: 0 1 2 3 4 5 6 7 8 9 
Dequeued: 0 1 2 3 4 5 6 7 8 9 
  • cscでコンパイルしたアセンブリ、RedHat Linux上のMonoで動作OK
  • mcsでコンパイルしたアセンブリ、Windows XP上の.NET Frameworkで動作OK

環境に依存する処理も無いので、全く同じ結果が出力されています。

§3 System.IO名前空間

続いて、System.IO名前空間に存在するクラスを利用してみます。

using System;
using System.IO;

namespace SamtaMarta.Samples.Mono.Compatibility
{
    class SystemIO
    {
        static void Main(string[] args)
        {
            // 論理ドライブ一覧の表示
            foreach ( string drive in Environment.GetLogicalDrives() )
            {
                Console.Write( "{0}, ", drive );
            }
            Console.WriteLine();
            Console.WriteLine();

            // ファイルの読み書き
            Console.WriteLine( "File IO" );

            FileStream stream = null;
            StreamWriter writer = null;
            StreamReader reader = null;

            try
            {

                stream = new FileStream( "test.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.None );

                writer = new StreamWriter( stream );

                writer.WriteLine( "Hello mono." );
                writer.WriteLine( "writing text file" );
                writer.WriteLine( stream.Name );

                writer.Flush();

                stream.Seek( 0, SeekOrigin.Begin );

                reader = new StreamReader( stream );

                while ( reader.Peek() != -1 )
                {
                    Console.WriteLine( reader.ReadLine() );
                }
            }
            finally
            {
                if ( stream != null ) stream.Close();
            }

            Console.WriteLine();

            // FileInfoクラス
            FileInfo file = new FileInfo( "test.txt" );

            Console.WriteLine( "FullName: {0}", file.FullName );
            Console.WriteLine( "Attributes: {0}", file.Attributes.ToString() );
            Console.WriteLine( "CreationTime:   {0}", file.CreationTime );
            Console.WriteLine( "LastWriteTime:  {0}", file.LastWriteTime );
            Console.WriteLine( "LastAccessTime: {0}", file.LastAccessTime );

            file.CopyTo( "../test.txt", true );

            if ( File.Exists( "../test.txt" ) ) Console.WriteLine( "File copyed." );

            file.Delete();

            if ( !File.Exists( "test.txt" ) ) Console.WriteLine( "File deleted." );

            Console.WriteLine();

            // DirectoryInfoクラス
            DirectoryInfo dir = file.Directory;

            Console.WriteLine( "FullName: {0}", dir.FullName );
            Console.WriteLine( "Attributes: {0}", dir.Attributes.ToString() );
            Console.WriteLine( "CreationTime:   {0}", dir.CreationTime );
            Console.WriteLine( "LastWriteTime:  {0}", dir.LastWriteTime );
            Console.WriteLine( "LastAccessTime: {0}", dir.LastAccessTime );

            Console.WriteLine( "Parent: {0}", dir.Parent.FullName );
            Console.WriteLine( "Root: {0}", dir.Root.FullName );

            Console.WriteLine();

            foreach ( FileSystemInfo info in dir.GetFileSystemInfos() )
            {
                Console.WriteLine( info.FullName );
            }

            Console.WriteLine();

            // Pathクラス
            Console.WriteLine( "AltDirectorySeparatorChar: {0}", Path.AltDirectorySeparatorChar );
            Console.WriteLine( "DirectorySeparatorChar:    {0}", Path.DirectorySeparatorChar );
            Console.WriteLine( "PathSeparator:             {0}", Path.PathSeparator );
            Console.WriteLine( "VolumeSeparatorChar:       {0}", Path.VolumeSeparatorChar );

            Console.Write( "InvalidPathChars: " );

            foreach ( char invalidPathChar in Path.InvalidPathChars )
            {
                Console.Write( "{0} ", invalidPathChar );
            }

            Console.WriteLine();
        }
    }
}
Monoでの実行結果
/, /boot, /home, /tmp, /usr, /usr/local, /var, 

File IO
Hello mono.
writing text file
test.txt

FullName: /home/santamarta/programming_cs/MonoCompatibility/System.IO/test.txt
Attributes: Archive
CreationTime:   2004/07/25 2:04:42
LastWriteTime:  2004/07/25 2:04:42
LastAccessTime: 2004/07/25 2:04:42
File copyed.
File deleted.

FullName: /home/santamarta/programming_cs/MonoCompatibility/System.IO
Attributes: Directory
CreationTime:   2004/07/25 2:04:42
LastWriteTime:  2004/07/25 2:04:42
LastAccessTime: 2004/07/25 2:04:42
Parent: /home/santamarta/programming_cs/MonoCompatibility
Root: /

/home/santamarta/programming_cs/MonoCompatibility/System.IO/SystemIO.cs
/home/santamarta/programming_cs/MonoCompatibility/System.IO/SystemIO.cs~
/home/santamarta/programming_cs/MonoCompatibility/System.IO/SystemIO.exe
/home/santamarta/programming_cs/MonoCompatibility/System.IO/SystemIO.txt

AltDirectorySeparatorChar: \
DirectorySeparatorChar:    /
PathSeparator:             :
VolumeSeparatorChar:       /
InvalidPathChars:
.NET Frameworkでの実行結果
A:\, C:\, D:\, E:\, F:\, G:\, H:\, I:\, J:\, K:\, L:\, 

File IO
Hello mono.
writing text file
D:\Temporaly\MonoCompatibility\test.txt

FullName: D:\Temporaly\MonoCompatibility\test.txt
Attributes: Archive
CreationTime:   2004/07/25 15:46:22
LastWriteTime:  2004/07/25 15:46:22
LastAccessTime: 2004/07/25 15:46:22
File copyed.
File deleted.

FullName: D:\Temporaly\MonoCompatibility
Attributes: Directory
CreationTime:   2004/07/24 19:13:44
LastWriteTime:  2004/07/25 15:46:22
LastAccessTime: 2004/07/25 15:46:22
Parent: D:\Temporaly
Root: D:\

D:\Temporaly\MonoCompatibility\System.exe
D:\Temporaly\MonoCompatibility\SystemCollection.exe
D:\Temporaly\MonoCompatibility\SystemDrawing.exe
D:\Temporaly\MonoCompatibility\SystemGlobalization.exe
D:\Temporaly\MonoCompatibility\SystemIO.exe
D:\Temporaly\MonoCompatibility\SystemRuntimeSerialization.exe
D:\Temporaly\MonoCompatibility\SystemSecurityCryptography.exe
D:\Temporaly\MonoCompatibility\SystemText.exe
D:\Temporaly\MonoCompatibility\SystemThreading.exe
D:\Temporaly\MonoCompatibility\SystemXml.exe

AltDirectorySeparatorChar: /
DirectorySeparatorChar:    \
PathSeparator:             ;
VolumeSeparatorChar:       :
InvalidPathChars: " < > |
  • cscでコンパイルしたアセンブリ、RedHat Linux上のMonoで動作OK
  • mcsでコンパイルしたアセンブリ、Windows XP上の.NET Frameworkで動作OK

Windows とLinuxでファイルシステムが異なっているため、論理ドライブ名は各ディレクトリとして出力されています。 ファイルの属性などはWindowsのファイルシステムのものが表示されるようになっています。 DirectorySeparatorCharなどはシステムに依存した値になっています。 また、ファイルへの書き込み、移動・コピーなども正常に行われました。

§4 System.Text名前空間

次はSystem.Text名前空間に存在するクラスを利用してみます。

using System;
using System.IO;
using System.Text;

namespace SamtaMarta.Samples.Mono.Compatibility
{
    class SystemText
    {
        static void Main(string[] args)
        {
            // エンコーディング
            Encoding[] encodings = new Encoding[] {
                                                    Encoding.Default,
                                                    Encoding.ASCII,
                                                    Encoding.UTF8,
                                                    Encoding.GetEncoding( "euc-jp" ),
                                                    Encoding.GetEncoding( "shift_jis" )
                                                };
            string[] fileNames = new string[] {
                                                "default.txt",
                                                "ascii.txt",
                                                "utf8.txt",
                                                "eucjp.txt",
                                                "shiftjis.txt"
                                            };

            for ( int index = 0; index < fileNames.Length; index++ )
            {
                Encoding encoding = encodings[index];
                string fileName = fileNames[index];

                FileStream stream = null;
                StreamWriter writer = null;

                try
                {
                    stream = new FileStream( fileName, FileMode.Create, FileAccess.Write, FileShare.None );
    
                    writer = new StreamWriter( stream, encoding );

                    writer.WriteLine( encoding.EncodingName );
                    writer.WriteLine( encoding.WebName );
                    writer.WriteLine( "1234567890" );
                    writer.WriteLine( "abcdefghij" );
                    writer.WriteLine( "あいう亜井宇" );

                    writer.Flush();
                }
                finally
                {
                    if ( stream != null ) stream.Close();
                }
            }
        }
    }
}
Monoでの実行結果 (default.txtの内容)
Japanese (EUC)
euc-jp
1234567890
abcdefghij
あいう亜井宇
.NET Frameworkでの実行結果 (default.txtの内容)
日本語 (シフト JIS)
shift_jis
1234567890
abcdefghij
あいう亜井宇
  • cscでコンパイルしたアセンブリ、RedHat Linux上のMonoで動作OK
  • mcsでコンパイルしたアセンブリ、Windows XP上の.NET Frameworkで動作OK

default.txt はシステムで用いられているエンコーディングで文字列を出力したファイルです。 LinuxではEUC-JP、WindowsではShiftJISを使用しているので上記の様な結果になっています。 また、ほかのエンコーディングで出力した結果もそれぞれ同じになっています。

§5 System.Threading名前空間

続いて、System.Threading名前空間に存在するクラスを利用してみます。

using System;
using System.Threading;

namespace SamtaMarta.Samples.Mono.Compatibility
{
    class SystemThreading
    {
        static void Main(string[] args)
        {
            Thread t = new Thread( new ThreadStart( CalculateA ) );

            t.Start();

            CalculateB();

            Console.WriteLine( "Finished" );
        }

        static void CalculateA()
        {
            int count = 0;

            while ( count++ < 10 )
            {
                Console.WriteLine( "CalculateA" ); 

                Thread.Sleep( 100 );
            }
        }

        static void CalculateB()
        {
            int count = 0;

            while ( count++ < 5 )
            {
                Console.WriteLine( "CalculateB" ); 

                Thread.Sleep( 250 );
            }
        }
    }
}
Monoでの実行結果
CalculateA
CalculateB
CalculateA
CalculateA
CalculateB
CalculateA
CalculateA
CalculateB
CalculateA
CalculateA
CalculateA
CalculateB
CalculateA
CalculateA
CalculateB
Finished
.NET Frameworkでの実行結果
CalculateB
CalculateA
CalculateA
CalculateA
CalculateB
CalculateA
CalculateA
CalculateB
CalculateA
CalculateA
CalculateA
CalculateB
CalculateA
CalculateA
CalculateB
Finished
  • cscでコンパイルしたアセンブリ、RedHat Linux上のMonoで動作OK
  • mcsでコンパイルしたアセンブリ、Windows XP上の.NET Frameworkで動作OK

実行順序はシステムの状態によって可変するので結果は異なっていますが、CalculateAとCalculateBはそれぞれ10回・5回ずつ呼び出されています。

§6 System.Globalization名前空間

次はSystem.Globalozation名前空間に存在するクラスを利用してみます。

using System;
using System.Threading;
using System.Globalization;

namespace SamtaMarta.Samples.Mono.Compatibility
{
    class SystemGlobalization
    {
        static void Main(string[] args)
        {
            // 現在のカルチャ
            CultureInfo culture = CultureInfo.CurrentCulture;

            Console.WriteLine( culture.Name );
            Console.WriteLine( culture.DisplayName );
            Console.WriteLine( culture.EnglishName );
            Console.WriteLine( culture.NativeName );
            Console.WriteLine( culture.ThreeLetterISOLanguageName );
            Console.WriteLine( culture.Calendar );
            Console.WriteLine( culture.TextInfo.ANSICodePage );
            Console.WriteLine( culture.NumberFormat.CurrencySymbol );

            Console.WriteLine();

            // 現在のスレッドのカルチャ
            Console.WriteLine( "CurrentCulture: {0}", CultureInfo.CurrentCulture.NativeName );

            Console.WriteLine( "{0:C}", 123456.789 );

            Console.WriteLine( "{0}", DateTime.Now );

            Console.WriteLine();

            // 現在のスレッドのカルチャを変更
            Thread.CurrentThread.CurrentCulture = new CultureInfo( "en-US" );

            Console.WriteLine( "CurrentCulture: {0}", CultureInfo.CurrentCulture.NativeName );

            Console.WriteLine( "{0:C}", 123456.789 );

            Console.WriteLine( "{0}", DateTime.Now );

            Console.WriteLine();

            // 現在のスレッドの暦を変更
            Thread.CurrentThread.CurrentCulture = new CultureInfo( "ja-JP" );

            Console.WriteLine( "{0}", DateTime.Now );

            Thread.CurrentThread.CurrentCulture.DateTimeFormat.Calendar = new JapaneseCalendar();

            Console.WriteLine( "{0}", DateTime.Now );

            Console.WriteLine();

            // インストールされているカルチャ
            foreach ( CultureInfo cul in CultureInfo.GetCultures( CultureTypes.AllCultures ) )
            {
                Console.WriteLine( cul.Name + ", " + cul.NativeName );
            }
        }
    }
}
Monoでの実行結果
ja-JP
Japanese (Japan)
Japanese (Japan)
日本語 (日本)
jpn
System.Globalization.GregorianCalendar
0
\

CurrentCulture: 日本語 (日本)
\123,457
2004/07/25 2:01:28

CurrentCulture: English (United States)
$123,456.79
7/25/2004 2:01:28 AM

2004/07/25 2:01:28
0016/07/25 2:01:28

ar, ???????
bg, Български
ca, catala
cs, ?e?tina
da, Dansk
de, Deutsch
el, Ελληνικ?
en, English
es, espanol
fi, suomi
fr, francais
he, ?????
hu, magyar
is, islenska
it, italiano
ja, 日本語
ko, ???
nl, Nederlands
pl, polski
pt, portugues
ro, Roman?
ru, Русский
hr, hrvatski
sk, slovensky
sq, shqipe
sv, svenska
th, ???
tr, Turkce
id, Bahasa Indonesia
uk, Укра?нська
be, Беларуск?
sl, Sloven??ina
et, Eesti
lv, latvie?u
lt, Lietuvi?
fa, ?????
vi, Ti?ng Vi?t
hy, ???????
eu, euskara
mk, македонски
af, Afrikaanse
fo, foroyskt
hi, ?????
sw, Kiswahili
gu, ???????
ta, ?????
te, ??????
kn, ?????
mr, ?????
gl, galego
kok, ??????
bg-BG, Български (България)
ca-ES, catala (Espanya)
cs-CZ, ?e?tina (?eska republika)
da-DK, Dansk (Danmark)
de-DE, Deutsch (Deutschland)
el-GR, Ελληνικ? (Ελλ?δα)
en-US, English (United States)
fi-FI, suomi (Suomi)
fr-FR, francais (France)
he-IL, ????? (?????)
hu-HU, magyar (Magyarorszag)
is-IS, islenska (Island)
it-IT, italiano (Italia)
ja-JP, 日本語 (日本)
ko-KR, ??? (????)
nl-NL, Nederlands (Nederland)
pl-PL, polski (Polska)
pt-BR, portugues (Brasil)
ro-RO, Roman? (Romania)
ru-RU, Русский (Россия)
hr-HR, hrvatski (Hrvatska)
sk-SK, slovensky (Slovenska republika)
sq-AL, shqipe (Shqiperia)
sv-SE, svenska (Sverige)
th-TH, ??? (?????????)
tr-TR, Turkce (Turkiye)
id-ID, Bahasa Indonesia (Indonesia)
uk-UA, Укра?нська (Укра?на)
be-BY, Беларуск? (Беларусь)
sl-SI, Sloven??ina (Slovenija)
et-EE, Eesti (Eesti)
lv-LV, latvie?u (Latvija)
lt-LT, Lietuvi? (Lietuva)
fa-IR, ????? (?????)
vi-VN, Ti?ng Vi?t (Vi?t Nam)
hy-AM, ??????? (????????? ??????????????)
hy-AM, ??????? (????????? ??????????????)
eu-ES, euskara (Espainia)
mk-MK, македонски (Македони?а)
af-ZA, Afrikaanse (Suid-Afrika)
fo-FO, foroyskt (Foroyar)
hi-IN, ????? (????)
sw-KE, Kiswahili (Kenya)
gu-IN, ??????? (????)
ta-IN, ????? (???????)
te-IN, ?????? (???? ????)
kn-IN, ????? (????)
mr-IN, ????? (????)
gl-ES, galego (Espana)
kok-IN, ?????? (????)
ar-IQ, ??????? (??????)
de-CH, Deutsch (Schweiz)
en-GB, English (United Kingdom)
es-MX, espanol (Mexico)
fr-BE, francais (Belgique)
it-CH, italiano (Svizzera)
nl-BE, Nederlands (Belgie)
pt-PT, portugues (Portugal)
sv-FI, svenska (Finland)
ar-EG, ??????? (???)
de-AT, Deutsch (Osterreich)
en-AU, English (Australia)
es-ES, espanol (Espana)
fr-CA, francais (Canada)
ar-LY, ??????? (?????)
de-LU, Deutsch (Luxemburg)
en-CA, English (Canada)
es-GT, espanol (Guatemala)
fr-CH, francais (Suisse)
ar-DZ, ??????? (???????)
en-NZ, English (New Zealand)
es-CR, espanol (Costa Rica)
fr-LU, francais (Luxembourg)
ar-MA, ??????? (??????)
en-IE, English (Ireland)
es-PA, espanol (Panama)
ar-TN, ??????? (????)
en-ZA, English (South Africa)
es-DO, espanol (Republica Dominicana)
ar-OM, ??????? (????)
es-VE, espanol (Venezuela)
ar-YE, ??????? (?????)
es-CO, espanol (Colombia)
ar-SY, ??????? (?????)
es-PE, espanol (Peru)
ar-JO, ??????? (??????)
es-AR, espanol (Argentina)
ar-LB, ??????? (?????)
en-ZW, English (Zimbabwe)
es-EC, espanol (Ecuador)
ar-KW, ??????? (??????)
en-PH, English (Philippines)
es-CL, espanol (Chile)
ar-AE, ??????? (???????? ??????? ???????)
es-UY, espanol (Uruguay)
ar-BH, ??????? (???????)
es-PY, espanol (Paraguay)
ar-QA, ??????? (???)
es-BO, espanol (Bolivia)
es-SV, espanol (El Salvador)
es-HN, espanol (Honduras)
es-NI, espanol (Nicaragua)
es-PR, espanol (Puerto Rico)
.NET Frameworkでの実行結果
ja-JP
日本語 (日本)
Japanese (Japan)
日本語 (日本)
jpn
System.Globalization.GregorianCalendar
932
\

CurrentCulture: 日本語 (日本)
\123,457
2004/07/25 16:10:28

CurrentCulture: English (United States)
$123,456.79
7/25/2004 4:10:28 PM

2004/07/25 16:10:28
平成 16/7/25 16:10:28

ar, ???????
ar-SA, ??????? (??????? ??????? ????????)
ar-IQ, ??????? (??????)
ar-EG, ??????? (???)
ar-LY, ??????? (?????)
ar-DZ, ??????? (???????)
ar-MA, ??????? (??????? ????????)
ar-TN, ??????? (????)
ar-OM, ??????? (????)
ar-YE, ??????? (?????)
ar-SY, ??????? (?????)
ar-JO, ??????? (??????)
ar-LB, ??????? (?????)
ar-KW, ??????? (??????)
ar-AE, ??????? (???????? ??????? ???????)
ar-BH, ??????? (???????)
ar-QA, ??????? (???)
bg, български
bg-BG, български (България)
ca, catala
ca-ES, catala (catala)
zh-CHS, 中文(?体)
zh-TW, 中文(繁體) (台灣)
zh-CN, 中文(?体) (中?人民共和国)
zh-HK, 中文(繁體) (香港特?行政区)
zh-SG, 中文(?体) (新加坡)
zh-MO, 中文(?体) (澳?特?行政区)
zh-CHT, 中文(繁體)
cs, ?e?tina
cs-CZ, ?e?tina (?eska?republika)
da, dansk
da-DK, dansk (Danmark)
de, Deutsch
de-DE, Deutsch (Deutschland)
de-CH, Deutsch (Schweiz)
de-AT, Deutsch (Osterreich)
de-LU, Deutsch (Luxemburg)
de-LI, Deutsch (Liechtenstein)
el, ελληνικ?
el-GR, ελληνικ? (Ελλ?δα)
en, English
en-US, English (United States)
en-GB, English (United Kingdom)
en-AU, English (Australia)
en-CA, English (Canada)
en-NZ, English (New Zealand)
en-IE, English (Eire)
en-ZA, English (South Africa)
en-JM, English (Jamaica)
en-CB, English (Caribbean)
en-BZ, English (Belize)
en-TT, English (Trinidad y Tobago)
en-ZW, English (Zimbabwe)
en-PH, English (Philippines)
es, espanol
es-MX, Espanol (Mexico)
es-ES, espanol (Espana)
es-GT, Espanol (Guatemala)
es-CR, Espanol (Costa Rica)
es-PA, Espanol (Panama)
es-DO, Espanol (Republica Dominicana)
es-VE, Espanol (Republica Bolivariana de Venezuela)
es-CO, Espanol (Colombia)
es-PE, Espanol (Peru)
es-AR, Espanol (Argentina)
es-EC, Espanol (Ecuador)
es-CL, Espanol (Chile)
es-UY, Espanol (Uruguay)
es-PY, Espanol (Paraguay)
es-BO, Espanol (Bolivia)
es-SV, Espanol (El Salvador)
es-HN, Espanol (Honduras)
es-NI, Espanol (Nicaragua)
es-PR, Espanol (Puerto Rico)
fi, suomi
fi-FI, suomi (Suomi)
fr, francais
fr-FR, francais (France)
fr-BE, francais (Belgique)
fr-CA, francais (Canada)
fr-CH, francais (Suisse)
fr-LU, francais (Luxembourg)
fr-MC, francais (Principaute de Monaco)
he, ?????
he-IL, ????? (?????)
hu, Magyar
hu-HU, Magyar (Magyarorszag)
is, islenska
is-IS, islenska (Island)
it, italiano
it-IT, italiano (Italia)
it-CH, italiano (Svizzera)
ja, 日本語
ja-JP, 日本語 (日本)
ko, ???
ko-KR, ??? (????)
nl, Nederlands
nl-NL, Nederlands (Nederland)
nl-BE, Nederlands (Belgie)
no, norsk
nb-NO, norsk (bokmal) (Norge)
nn-NO, norsk (nynorsk) (Noreg)
pl, polski
pl-PL, polski (Polska)
pt, Portugues
pt-BR, Portugues (Brasil)
pt-PT, portugues (Portugal)
ro, roman?
ro-RO, roman? (Romania)
ru, русский
ru-RU, русский (Россия)
hr, hrvatski
hr-HR, hrvatski (Hrvatska)
sr-SP-Latn, srpski (Srbija)
sr-SP-Cyrl, српски (?угослави?а)
sk, sloven?ina
sk-SK, sloven?ina (Slovenska republika)
sq, shqipe
sq-AL, shqipe (Shqiperia)
sv, svenska
sv-SE, svenska (Sverige)
sv-FI, svenska (Finland)
th, ???
th-TH, ??? (???)
tr, Turkce
tr-TR, Turkce (Turkiye)
ur, ?????
ur-PK, ????? (???????)
id, Bahasa Indonesia
id-ID, Bahasa Indonesia (Indonesia)
uk, укра?ньска
uk-UA, укра?ньска (Укра?на)
be, Беларуск?
be-BY, Беларуск? (Беларусь)
sl, slovenski
sl-SI, slovenski (Slovenija)
et, eesti
et-EE, eesti (Eesti)
lv, latvie?u
lv-LV, latvie?u (Latvija)
lt, lietuvi?
lt-LT, lietuvi? (Lietuva)
fa, ?????
fa-IR, ????? (?????)
vi, Tie?ng Vie?t Nam
vi-VN, Tie?ng Vie?t Nam (Vie?t Nam)
hy, ???????
hy-AM, ??????? (????????)
az, Az?rbaycan-?l?
az-AZ-Latn, Az?rbaycan-?l? (Az?rbaycanca)
az-AZ-Cyrl, Аз?рба??ан (Аз?рба??ан)
eu, euskara
eu-ES, euskara (euskara)
mk, македонски ?азик
mk-MK, македонски ?азик (Македони?а)
af, Afrikaans
af-ZA, Afrikaans (Suid Afrika)
ka, ???????
ka-GE, ??????? (??????????)
fo, foroyskt
fo-FO, foroyskt (Foroyar)
hi, ?????
hi-IN, ????? (????)
ms, Bahasa Malaysia
ms-MY, Bahasa Malaysia (Malaysia)
ms-BN, Bahasa Malaysia (Brunei Darussalam)
kk, ?азащb
kk-KZ, ?аза? (?аза?стан)
ky, Кыргыз
ky-KZ, Кыргыз (Кыргызстан)
sw, Kiswahili
sw-KE, Kiswahili (Kenya)
uz, U'zbek
uz-UZ-Latn, U'zbek (U'zbekiston Respublikasi)
uz-UZ-Cyrl, ?збек (?збекистон)
tt, Татар
tt-RU, Татар (Россия)
pa, ??????
pa-IN, ?????? (????)
gu, ???????
gu-IN, ??????? (????)
ta, ?????
ta-IN, ????? (???????)
te, ??????
te-IN, ?????? (?????????)
kn, ?????
kn-IN, ????? (????)
mr, ?????
mr-IN, ????? (????)
sa, ???????
sa-IN, ??????? (??????)
mn, Монгол?хэл
mn-MN, Монгол?хэл (Монгол?улс)
gl, galego
gl-ES, galego (galego)
kok, ??????
kok-IN, ?????? (????)
syr, ??????
syr-SY, ?????? (?????)
div, ??????????
div-MV, ?????????? (?????? ??????)
, Invariant Language (Invariant Country)
  • cscでコンパイルしたアセンブリ、RedHat Linux上のMonoで動作OK
  • mcsでコンパイルしたアセンブリ、Windows XP上の.NET Frameworkで動作OK

現在のスレッドのカルチャを取得・設定したり、暦を変更したりすることも問題なく出来ています。 表示されたカルチャセットに相違があるのは、カルチャセットがシステムに存在するか否かによるからです。

§7 System.Security.Cryptography名前空間

続いては、System.Security.Cryptography名前空間に存在するクラスを利用してDESアルゴリズムによる暗号化・復号化を試みます。

using System;
using System.IO;
using System.Text;
using System.Security;
using System.Security.Cryptography;

namespace SamtaMarta.Samples.Mono.Compatibility
{
    class SystemSecurityCryptography
    {
        static void Main(string[] args)
        {
            // 鍵(8バイト)
            byte[] key = Encoding.ASCII.GetBytes( "password" );

            // 原文
            MemoryStream originalStream = new MemoryStream();

            StreamWriter writer = new StreamWriter( originalStream, Encoding.Unicode );

            writer.WriteLine( "0123456789" );
            writer.WriteLine( "ABCDEFG" );
            writer.WriteLine( "あいうえお" );
            writer.WriteLine( "アイウエオ" );
            writer.WriteLine( "亜井宇江尾" );

            writer.Flush();

            Output( originalStream.ToArray() );

            // 暗号化
            MemoryStream encryptedStream = new MemoryStream( 128 );

            EncryptByDES( originalStream.ToArray(), encryptedStream, key );

            Output( encryptedStream.ToArray() );

            // 復号化
            MemoryStream decryptedStream = new MemoryStream( 128 );

            DecryptByDES( encryptedStream.ToArray(), decryptedStream, key );

            Output( decryptedStream.ToArray() );
        }

        // 暗号化
        static void EncryptByDES( byte[] original, Stream encryptedStream, byte[] encryptionKey )
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();

            des.Key = encryptionKey;
            des.IV = encryptionKey;

            CryptoStream cryptoStream = null;
            
            try
            {
                cryptoStream = new CryptoStream( encryptedStream, des.CreateEncryptor(), CryptoStreamMode.Write);

                cryptoStream.Write( original, 0, original.Length );
            }
            finally
            {
                if ( cryptoStream != null ) cryptoStream.Close();
            }
        }

        // 復号化
        static void DecryptByDES( byte[] encrypted, Stream decryptedStream, byte[] decryptionKey )
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();

            des.Key = decryptionKey;
            des.IV = decryptionKey;

            CryptoStream cryptoStream = null;
            
            try
            {
                cryptoStream = new CryptoStream( decryptedStream, des.CreateDecryptor(), CryptoStreamMode.Write);

                cryptoStream.Write( encrypted, 0, encrypted.Length );
            }
            finally
            {
                if ( cryptoStream != null ) cryptoStream.Close();
            }
        }

        // 出力
        static void Output( byte[] text )
        {
            MemoryStream stream = new MemoryStream( text );
            
            StreamReader reader = new StreamReader( stream, Encoding.Unicode );

            Console.WriteLine( reader.ReadToEnd() );

            Console.WriteLine();

            reader.Close();
        }
    }
}
Monoでの実行結果
0123456789
ABCDEFG
あいうえお
アイウエオ
亜井宇江尾


???????????????????鮫??幹??????????????N

0123456789
ABCDEFG
あいうえお
アイウエオ
亜井宇江尾
.NET Frameworkでの実行結果
0123456789
ABCDEFG
あいうえお
アイウエオ
亜井宇江尾


???????????梅?冉??颯?????????蹇?元?????????ノ?????

0123456789
ABCDEFG
あいうえお
アイウエオ
亜井宇江尾
  • cscでコンパイルしたアセンブリ、RedHat Linux上のMonoで動作OK
  • mcsでコンパイルしたアセンブリ、Windows XP上の.NET Frameworkで動作OK

暗号化・復号化ともに問題なく動作しています。

§8 System.Runtime.Serialization名前空間

System.Runtime.Serialization名前空間に存在するクラスを用いて、バイナリシリアル化を実行してみます。

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace SamtaMarta.Samples.Mono.Compatibility
{
    class SystemRuntimeSerialization
    {
        static void Main(string[] args)
        {
            SerializationTarget s = new SerializationTarget( "test", 12345, 3.1415, 2.718m );

            Console.WriteLine( s );
            Console.WriteLine();

            byte[] serialized = Serialize( s );

            Dump( serialized );
            Console.WriteLine();

            Console.WriteLine( Deserialize( serialized ) );
            Console.WriteLine();
        }

        // シリアル化
        static byte[] Serialize( SerializationTarget s )
        {
            MemoryStream stream = new MemoryStream();

            BinaryFormatter formatter = new BinaryFormatter( null, new StreamingContext( StreamingContextStates.All ) );

            formatter.Serialize( stream, s );

            stream.Close();

            return stream.ToArray();
        }

        // 逆シリアル化
        static SerializationTarget Deserialize( byte[] serialized )
        {
            SerializationTarget s;

            MemoryStream stream = new MemoryStream( serialized );

            BinaryFormatter formatter = new BinaryFormatter( null, new StreamingContext( StreamingContextStates.All ) );

            s = formatter.Deserialize( stream ) as SerializationTarget;

            stream.Close();

            return s;
        }

        // ダンプ
        static void Dump( byte[] arr )
        {
            int pos = 0;
            int len = arr.Length;

            do
            {
                int i;
                int c;

                if ( len <= pos + 0x10 ) 
                {
                    c = len - pos;
                }
                else
                {
                    c = 0x10;
                }

                for ( i = 0; i <= c - 1; i += 1 )
                {
                    Console.Write( "{0:X2} ", arr[pos + i]);
                }

                Console.WriteLine();

                pos += 0x10;

            } while ( !( ( len <= pos ) ) );
        }
    }

    /// <summary>
    /// シリアル化の対象となるクラス
    /// </summary>
    [Serializable()]
    class SerializationTarget : ISerializable
    {
        private string  stringValue;
        private int     intValue;
        private double  doubleValue;
        private decimal decimalValue;

        public SerializationTarget( string stringValue, int intValue, double doubleValue, decimal decimalValue )
        {
            this.stringValue  = stringValue;
            this.intValue     = intValue;
            this.doubleValue  = doubleValue;
            this.decimalValue = decimalValue;
        }

        // 逆シリアル化に必要な暗黙のコンストラクタ
        private SerializationTarget( SerializationInfo info, StreamingContext context )
        {
            this.stringValue  = info.GetString( "String" );
            this.intValue     = info.GetInt32( "Int32" );
            this.decimalValue = info.GetDecimal( "Decimal" );
        }

        // GetObjectData()メソッドの実装
        public void GetObjectData( SerializationInfo info, StreamingContext context )
        {
            info.AddValue( "String",  this.stringValue );
            info.AddValue( "Int32",   this.intValue );
            info.AddValue( "Decimal", this.decimalValue );

            // doubleValueはシリアル化しない
        }

        public override string ToString()
        {
            return String.Format( "{{stringValue:{0}, intValue:{1}, doubleValue:{2}, decimalValue:{3}}}", stringValue, intValue, doubleValue, decimalValue );
        }
    }
}
Monoでの実行結果
{stringValue:test, intValue:12345, doubleValue:3.1415, decimalValue:2.718}

00 01 00 00 00 FF FF FF FF 01 00 00 00 00 00 00 
00 0C 02 00 00 00 51 53 79 73 74 65 6D 52 75 6E 
74 69 6D 65 53 65 72 69 61 6C 69 7A 61 74 69 6F 
6E 2C 20 56 65 72 73 69 6F 6E 3D 30 2E 30 2E 30 
2E 30 2C 20 43 75 6C 74 75 72 65 3D 6E 65 75 74 
72 61 6C 2C 20 50 75 62 6C 69 63 4B 65 79 54 6F 
6B 65 6E 3D 6E 75 6C 6C 05 01 00 00 00 39 53 61 
6D 74 61 4D 61 72 74 61 2E 53 61 6D 70 6C 65 73 
2E 4D 6F 6E 6F 2E 43 6F 6D 70 61 74 69 62 69 6C 
69 74 79 2E 53 65 72 69 61 6C 69 7A 61 74 69 6F 
6E 54 61 72 67 65 74 03 00 00 00 06 53 74 72 69 
6E 67 05 49 6E 74 33 32 07 44 65 63 69 6D 61 6C 
01 00 00 08 05 02 00 00 00 06 03 00 00 00 04 74 
65 73 74 39 30 00 00 05 32 2E 37 31 38 0B 

{stringValue:test, intValue:12345, doubleValue:0, decimalValue:2.718}
.NET Frameworkでの実行結果
{stringValue:test, intValue:12345, doubleValue:3.1415, decimalValue:2.718}

00 01 00 00 00 FF FF FF FF 01 00 00 00 00 00 00 
00 0C 02 00 00 00 51 53 79 73 74 65 6D 52 75 6E 
74 69 6D 65 53 65 72 69 61 6C 69 7A 61 74 69 6F 
6E 2C 20 56 65 72 73 69 6F 6E 3D 30 2E 30 2E 30 
2E 30 2C 20 43 75 6C 74 75 72 65 3D 6E 65 75 74 
72 61 6C 2C 20 50 75 62 6C 69 63 4B 65 79 54 6F 
6B 65 6E 3D 6E 75 6C 6C 05 01 00 00 00 39 53 61 
6D 74 61 4D 61 72 74 61 2E 53 61 6D 70 6C 65 73 
2E 4D 6F 6E 6F 2E 43 6F 6D 70 61 74 69 62 69 6C 
69 74 79 2E 53 65 72 69 61 6C 69 7A 61 74 69 6F 
6E 54 61 72 67 65 74 03 00 00 00 06 53 74 72 69 
6E 67 05 49 6E 74 33 32 07 44 65 63 69 6D 61 6C 
01 00 00 08 05 02 00 00 00 06 03 00 00 00 04 74 
65 73 74 39 30 00 00 05 32 2E 37 31 38 0B 

{stringValue:test, intValue:12345, doubleValue:0, decimalValue:2.718}
  • cscでコンパイルしたアセンブリ、RedHat Linux上のMonoで動作OK
  • mcsでコンパイルしたアセンブリ、Windows XP上の.NET Frameworkで動作OK

シリアル化・逆シリアル化は正常に行われています。 ダンプ結果も同じ事から、Monoでシリアル化したデータを.NET Frameworkで逆シリアル化する事、またその逆も可能であると考えられます。

§9 System.Xml名前空間

最後にSystem.Xml名前空間に存在するクラスを利用して簡単なXML文書(RSS)を作成してみます。

using System;
using System.Xml;

namespace SamtaMarta.Samples.Mono.Compatibility
{
    class SystemXml
    {
        static void Main(string[] args)
        {
            XmlDocument document = new XmlDocument();

            // ?xml
            document.AppendChild( document.CreateXmlDeclaration( "1.0", "utf-8", "" ) );

            // rss
            XmlElement elementRss = document.CreateElement( "rss" );

            elementRss.SetAttribute( "version", "2.0" );

            document.AppendChild( elementRss );


            // rss/channel
            XmlElement elementRssChannel = document.CreateElement( "channel" );

            elementRss.AppendChild( elementRssChannel );

            // rss/channel/title
            XmlElement elementRssChannelTitle = document.CreateElement( "title" );

            elementRssChannelTitle.AppendChild( document.CreateTextNode( ".NETでいきまっしょい!" ) );

            elementRssChannel.AppendChild( elementRssChannelTitle );

            // rss/channel/link
            XmlElement elementRssChannelLink = document.CreateElement( "link" );

            elementRssChannelLink.AppendChild( document.CreateTextNode( "http://santamartadotnet.hp.infoseek.co.jp/" ) );

            elementRssChannel.AppendChild( elementRssChannelLink );

            // rss/channel/webMaster
            XmlElement elementRssChannelWebmaster = document.CreateElement( "webMaster" );

            elementRssChannelWebmaster.AppendChild( document.CreateTextNode( "santamartaofthepeace@hotmail.com" ) );

            elementRssChannel.AppendChild( elementRssChannelWebmaster );


            // rss/item
            XmlElement elementRssItem = document.CreateElement( "item" );

            elementRss.AppendChild( elementRssItem );

            // rss/item/title
            XmlElement elementRssItemTitle = document.CreateElement( "title" );

            elementRssItemTitle.AppendChild( document.CreateTextNode( "samlpe RSS item" ) );

            elementRssItem.AppendChild( elementRssItemTitle );

            // rss/item/link
            XmlElement elementRssItemLink = document.CreateElement( "link" );

            elementRssItemLink.AppendChild( document.CreateTextNode( "http://santamartadotnet.hp.infoseek.co.jp/" ) );

            elementRssItem.AppendChild( elementRssItemLink );

            // rss/item/pubDate
            XmlElement elementRssItemPubdate = document.CreateElement( "pubDate" );

            elementRssItemPubdate.AppendChild( document.CreateTextNode( DateTime.UtcNow.ToString("r", System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat) ) );

            elementRssItem.AppendChild( elementRssItemPubdate );


            // ファイルに保存
            document.Save( "rss.xml" );
        }
    }
}
Monoでの実行結果 (rss.xml)
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>.NETでいきまっしょい!</title>
    <link>http://santamartadotnet.hp.infoseek.co.jp/</link>
    <webMaster>santamartaofthepeace@hotmail.com</webMaster>
  </channel>
  <item>
    <title>samlpe RSS item</title>
    <link>http://santamartadotnet.hp.infoseek.co.jp/</link>
    <pubDate>Sat, 24 Jul 2004 17:10:03 GMT</pubDate>
  </item>
</rss>
.NET Frameworkでの実行結果 (rss.xml)
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>.NETでいきまっしょい!</title>
    <link>http://santamartadotnet.hp.infoseek.co.jp/</link>
    <webMaster>santamartaofthepeace@hotmail.com</webMaster>
  </channel>
  <item>
    <title>samlpe RSS item</title>
    <link>http://santamartadotnet.hp.infoseek.co.jp/</link>
    <pubDate>Sun, 25 Jul 2004 07:25:44 GMT</pubDate>
  </item>
</rss>
  • cscでコンパイルしたアセンブリ、RedHat Linux上のMonoで動作OK
  • mcsでコンパイルしたアセンブリ、Windows XP上の.NET Frameworkで動作OK

双方ともに全く問題なく動作しています。

§10 まとめ

今回はコアライブラリに含まれる基本的なクラスだけを抜粋して検証してきましたが、システムに依存する部分を除けばその全てについて.NET Frameworkと完全に同じ結果が得られる事が分かりました。 他のクラスについてもほぼ同様だと考えられます。 また、mcsでコンパイルしたアセンブリもcscでコンパイルしたアセンブリも、Monoおよび.NET Frameworkのどちらでも動作することが確認できました。 このことからも分かるとおり、今回調査したコアライブラリのクラスだけについて見れば、 Monoは.NET Frameworkと完全な互換性を持っているということが言えると思います。