2013-02-22 13 views
7

Javaでは、finalは、変数を1回だけ割り当てることができますが、その割り当てはプログラム内のどこでも実行できます。 C#では、readonlyは、コンストラクタでのみフィールドを割り当てることができることを意味します。このIMOは、あまり有用ではありません。C#readonly vs Java final

C#はJavaの設計の影響を強く受けましたが、この違いは常に私を非常に奇妙に思っています。誰もがの技術的な理由がCLRにあると、C#が役に立たない振る舞いをしているかどうかを知ることができますか?readonly対Javaのfinal

編集:

コメントに応じて;私は不変性の恩恵をよく知っていることを指摘したいと思います。私はそれを全面的に使います。

public class Foo 
{ 
    private readonly int _bar; 

    Foo() 
    { 
     _bar = 5; 
    } 
} 

おっと、私は実際にヘルパーメソッドでその値を初期化する必要があります:私はreadonlyは、このためのJavaよりもあまり有用であると考えています!

public class Foo 
{ 
    private readonly int _bar; 

    Foo() 
    { 
     initialize() 
    } 

    private void initialize() 
    { 
     _bar = 5; //Can't compile because of semantics of readonly 
    }  
} 
+25

あなたの「あまり役に立たない」は私の「より安全」です。 – Oded

+2

不変性のメリットは何ですか?私は 'readonly'がコンパイラにとって非常に有用であることがわかると思います。あなたは本質的に主観的です。 – Jodrell

+2

Javaのプログラムのどこでも最終的な変数に値を渡すことはできません。静的な最終定数を作成する場合は、変数を最終的に作成してからコンストラクタで変数を初期化できる場合は、その場で値を与える必要があります。 – ankurtr

答えて

12
あり

readonlyの行動のための技術的な理由です:作成したアセンブリのメタデータ内のフィールドは、フィールドがコンストラクタ外に変更されていないことを確認しますinitonly属性でマークされています。 しかし、確認できないものの、読み取り専用フィールドのアドレスを取ることによって、その値を変更することは可能です。検証可能なILとC#ではこれを許可しません。

コンパイラは、メソッドが呼び出される可能性のあるすべての可能な注文を、と呼ぶことができるため、コンパイラはすべてのメソッドに対してこれを強制することはできません。実行時には、おそらくCLRに負担がかかり、すべてのフィールドが以前に書き込まれたかどうかを確認する必要がある場合は、パフォーマンスが低下します。代わりに、C#とCLRは、コンストラクタの慎重に分析された範囲以外では、フィールドに値を割り当てることを許可しない方が安全です。

私の意見では、readonlyキーワードの価値はそれほど高くありません。コンストラクタ(例:リストの作成、またはコンストラクタ引数の格納など)によってのみ値がに提供されているフィールドのすべての場所で使用します。 C#は私がそれ以降フィールドを変更しないようにして、誤ってnullなどに設定することはできません。

)これを指摘してくれたEric Lippertに感謝します。

+0

@EricLippert:それを指摘してくれてありがとう。私は毎日何か新しいことを学ぶ... – Virtlink

+0

あなたは大歓迎です! –

+0

@Virtlinkご回答いただきありがとうございます。誰もが物事を終わらせるための言い訳を探すのではないというのはいいことです。 – MgSam