これについて同僚と友好的な議論をする。私たちはこれについていくつかの考えを持っていますが、SOの観衆はこれについてどう思いますか?
これについて同僚と友好的な議論をする。私たちはこれについていくつかの考えを持っていますが、SOの観衆はこれについてどう思いますか?
回答:
1つの理由は、読み取り専用ローカルに対するCLRサポートがないことです。ReadonlyはCLR / CLI initonlyオペコードに変換されます。このフラグはフィールドにのみ適用でき、ローカルには意味がありません。実際、これをローカルに適用すると、検証できないコードが生成される可能性があります。
これは、C#がこれを実行できなかったという意味ではありません。しかし、同じ言語構造に2つの異なる意味を与えます。ローカル用のバージョンには、CLRと同等のマッピングはありません。
readonly
フィールドのキーワードは、その効果が他のアセンブリから見えるため、CLIでサポートする必要があります。つまり、変数はコンパイル時にメソッドに1つしか割り当てられません。
const
(C ++では、C#readonly
よりもC#const
に似ていますが、両方の役割を果たすことができます)。しかし、C ++はconst
ローカル自動変数をサポートしています。したがって、readonly
ローカル変数のC#に対するCLRサポートの欠如は関係ありません。
using
とout
、世界が崩壊しなかったことを正確に行っています。
C#アーキテクトの一部にとって、これは悪い判断だと思います。ローカル変数のreadonly修飾子は、プログラムの正確性を維持するのに役立ち(アサートのように)、コンパイラーがコードを最適化するのに役立つ可能性があります(少なくとも他の言語の場合)。現在C#で許可されていないという事実は、C#の「機能」の一部が、その作成者の個人的なコーディングスタイルの実施にすぎないという別の議論です。
Jaredの答えに対処するには、それはおそらくコンパイル時の機能でなければなりません-コンパイラーは、最初の宣言(割り当てを含める必要があります)の後、変数への書き込みを禁止します。
これで価値を見ることはできますか?潜在的に-正直に言って、多くはありません。変数がメソッドの他の場所に割り当てられるかどうかを簡単に判断できない場合、メソッドが長すぎます。
何それの価値については、Javaは、(使用して、この機能があるfinal
修飾子を)と私がきた非常に稀にそれは例以外の使用は見られない持っている変数は、匿名内部クラスで捕捉できるようにするために使用される-それはどこであります使用すると、有用な情報というよりは、散らかった印象になります。
readonly
/ final
その持つ変数から値をval
してvar
、キーワード。Scalaコードでは、ローカルval
sは非常に頻繁に使用されます(実際、ローカルvar
s よりも優先されます)。final
修飾子がJavaでより頻繁に使用されない主な理由は、a)乱雑さとb)怠惰であると思います。
readonly
あまり重要ではありません。一方、クロージャで使用されるローカル変数のreadonly
場合、多くの場合、コンパイラにより効率的なコードが生成されます。現在、クロージャーを含むブロックに実行が入ると、クロージャーを使用するコードが実行されない場合でも、コンパイラーはクローズされた変数の新しいヒープオブジェクトを作成する必要があります。変数が読み取り専用の場合、クロージャーの外側のコードは通常の変数を使用できます。クロージャのデリゲートが作成された場合のみ
の読み取り専用のローカルとパラメーターの提案は、C#7設計チームによって簡単に議論されました。2015年1月21日のためのC#デザインミーティングノート:
パラメータとローカルはラムダによってキャプチャされ、それによって同時にアクセスできますが、共有相互状態の問題からそれらを保護する方法はありません。読み取り専用にすることはできません。
一般に、ほとんどのパラメーターと多くのローカル変数は、初期値を取得した後に割り当てられることは決してありません。それらに読み取り専用を許可すると、その意図が明確に表現されます。
1つの問題は、この機能が「魅力的な迷惑」になる可能性があることです。ほとんどの場合、「正しいこと」はパラメータとローカルを読み取り専用にすることですが、そうすることでコードが乱雑になります。
これを部分的に緩和するアイデアは、ローカル変数のreadonly varの組み合わせをvalまたはそのような短いものに縮小できるようにすることです。より一般的には、確立された読み取り専用よりも短いキーワードを単純に考えて、読み取り専用性を表現することができます。
C#言語設計リポジトリで議論が続けられています。投票して支持を表明しましょう。https://github.com/dotnet/csharplang/issues/188
Readonlyは、インスタンス変数を設定できる唯一の場所がコンストラクター内であることを意味します。変数をローカルに宣言する場合、インスタンスはなく(スコープ内にあるだけ)、コンストラクターから変更することはできません。
私は知っています、これはあなたの質問の理由に答えません。とにかく、この質問を読んでいる人はそれでも以下のコードに感謝するかもしれません。
一度だけ設定する必要があるローカル変数をオーバーライドするときに自分の足を撃つことに本当に関心があり、よりグローバルにアクセスできる変数にしたくない場合は、次のようにすることができます。
public class ReadOnly<T>
{
public T Value { get; private set; }
public ReadOnly(T pValue)
{
Value = pValue;
}
public static bool operator ==(ReadOnly<T> pReadOnlyT, T pT)
{
if (object.ReferenceEquals(pReadOnlyT, null))
{
return object.ReferenceEquals(pT, null);
}
return (pReadOnlyT.Value.Equals(pT));
}
public static bool operator !=(ReadOnly<T> pReadOnlyT, T pT)
{
return !(pReadOnlyT == pT);
}
}
使用例:
var rInt = new ReadOnly<int>(5);
if (rInt == 5)
{
//Int is 5 indeed
}
var copyValueOfInt = rInt.Value;
//rInt.Value = 6; //Doesn't compile, setter is private
たぶんコードは少なくありませんrvar rInt = 5
が、動作します。
C#インタラクティブコンパイラを使用している場合は、C#で読み取り専用ローカル変数を宣言できますcsi
。
>"C:\Program Files (x86)\MSBuild\14.0\Bin\csi.exe"
Microsoft (R) Visual C# Interactive Compiler version 1.3.1.60616
Copyright (C) Microsoft Corporation. All rights reserved.
Type "#help" for more information.
> readonly var message = "hello";
> message = "goodbye";
(1,1): error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
.csx
スクリプト形式で読み取り専用のローカル変数を宣言することもできます。
message
ここでは変数ではなく、フィールドにコンパイルされます。対話型のC#にも明確な違いがあるため、これは問題になりません:int x; Console.WriteLine(x)
有効な対話型C#です(x
フィールドであり、暗黙的に初期化されるvoid foo() { int x; Console.WriteLine(x); }
ため)が、そうではありません(x
変数であり、割り当て前に使用されるため)。また、Expression<Func<int>> y = x; ((MemberExpression) y.Body).Member.MemberType
これx
は実際にはフィールドであり、ローカル変数ではありません。
c#には、多少異なる構文ではありますが、すでに読み取り専用の変数があります。
次の行を検討してください。
var mutable = myImmutableCalculationMethod();
readonly var immutable = mutable; // not allowed in C# 8 and prior versions
return immutable;
と比べて:
var mutable = myImmutableCalculationMethod();
string immutable() => mutable; // allowed in C# 7
return immutable();
確かに、最初の解決策はおそらく書くコードが少ないかもしれません。ただし、2番目のスニペットは、変数を参照するときに読み取り専用を明示的にします。
readonly var im = new List<string>(); im.Add("read-only variable, mutable object!");
。
const
キーワードを使用して、読み取り専用変数にします。
リファレンス:https : //docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const
public class SealedTest
{
static void Main()
{
const int c = 707;
Console.WriteLine("My local constant = {0}", c);
}
}
const
変数が初期化中にのみ割り当てられるJavaScriptスタイルに興味がありますconst
。コンパイル時の式のみが使用されるcsharpスタイルには興味がありません。たとえば、あなたがすることはできませんconst object c = new object();
が、readonly
ローカルはこれを行うことができます。