興味深い「params of ref」機能ですが、何か回避策はありますか?
-
21-09-2019 - |
質問
値型でこのようなことが可能になる方法はあるのだろうか...
public static class ExtensionMethods {
public static void SetTo(this Boolean source, params Boolean[] bools) {
for (int i = 0; i < bools.Length; i++) {
bools[i] = source;
}
}
}
そうすれば、これが可能になります:
Boolean a = true, b, c = true, d = true, e;
b.SetTo(a, c, d, e);
もちろん、これは機能しません。ブール値は値型であり、参照としてではなく値として関数に渡されるからです。
(別のクラスを作成して) 値の型を参照型にラップする以外に、params 修飾子を使用しながら参照 (ref) によって変数を関数に渡す方法はありますか?
解決
これは不可能です。その理由を説明するには、まず、値型のローカル変数をスタックに置くことでその割り当て解除を最適化する理由についての私のエッセイを読んでください。
それを理解したので、「ref bool」を配列に格納できない理由が明らかになるはずです。可能であれば、参照されているスタック変数よりも長く存続する配列を作成できます。選択肢は 2 つあります。これを許可するか、間違った場合にクラッシュしてひどく死んでしまうプログラムを作成するかのどちらかです。これは C の設計者が行った選択です。あるいは、それを禁止し、柔軟性は低いがより安全なシステムを採用します。私たちは後者を選びました。
しかし、これについてもう少し深く考えてみましょう。「変数を設定できるようにするもの」を渡したい場合は、次のようになります。 それ. 。それは単なる代理人です:
static void DoStuff<T>(this T thing, params Action<T>[] actions)
{
foreach(var action in actions) action(thing);
}
...
bool b = whatever;
b.DoStuff(x=>{q = x;}, x=>{r = x;} );
意味をなす?
他のヒント
のJavaの不幸なコミュニティ、そして今.NETは、開発者が(「安全」の名前ではあまり柔軟性が好ましい解決策であると判断し、異常な複雑さのためにOPTにあなたが持っているコードの少ない行と同じ結果を達成するためにこれらすべてのクラス構造、代表団、など。)。
でデルファイ私は単にこのような何かを行うことができます:
var
a: integer; f: double; n: integer;
sscanf(fmtstr, valuestr, [@a, @f, @n]);
// < - 。「sscanf関数は、」ポインタのオープン配列を受け取り、私は自分自身を書いた関数である。
でCあなたがしなければならないでしょう。#ます:
int a; double f; int n;
object [] o = new object[];
sscanf(fmtstr, valuestr, ref o);
a = o[0];
f = o[1];
n = o[2];
私はDelphiコードの1行目に何ができるかやってコードの5行です。私は、コードのバグの可能性は、コードの行数と幾何学的に増加することを公式のどこかがあると思います。あなたは、コードの20行を持っている場合ので、あなたがしているコードは、あなたが10を持っている場合よりも、バグを持って4倍以上の可能性があります。
もちろん、あなたがすべてのそれらの奇妙な角括弧と奇妙な構文でデリゲートを使用することにより、コードのあなたの#行を減らすことができますが、私はそれはまた、バグのための避難所だと思います。
の方法は本当にありません。あなたはこのような何かを行うことができます:
public static void Main(string[] args)
{
BooleanWrapper a = true, b = true, c = true, d = true, e = new BooleanWrapper();
b.SetTo(a, c, d, e);
}
public static void SetTo(this BooleanWrapper sourceWrapper, params BooleanWrapper[] wrappers)
{
foreach (var w in wrappers)
w.Value = sourceWrapper.Value;
}
public class BooleanWrapper
{
public BooleanWrapper() { }
public BooleanWrapper(Boolean value)
{
Value = value;
}
public Boolean Value { get; set; }
public static implicit operator BooleanWrapper(Boolean value)
{
return new BooleanWrapper(value);
}
}
しかし、その後、再びどのようにちょうどこれを行うよりも良くあることです。
public static void Main(string[] args)
{
Boolean[] bools = new Boolean[5];
bools.SetTo(bools[1]); // Note I changed the order of arguments. I think this makes more sense.
}
public static void SetTo(this Boolean[] bools, Boolean value)
{
for(int i = 0; i < bools.Length; i++)
bools[i] = value;
}
すべての後、配列のの変数のシーケンスです。あなたは、変数の順序のような振る舞いは、配列を使用することを何かが必要な場合。
このはbool
sは、参照型であったとしても不可能であろう。 class
が参照型である一方、Boolean[]
内の変数は、まだの値のある、それだけです。の値のはの参照のであること。基準の値を代入するだけで、その特定の変数の値を変更します。 ref
変数の配列の概念は(その性質、一連の値によって、配列がそうであるように)意味がありません。