私は多くの計算、特に乗算を行っています。最初の部分がゼロの場合があり、その場合は 2 番目のオペランドを評価したくありません。C# には少なくとも 2 つの短絡演算子があります: &&
and||
は、必要な場合にのみ 2 番目のオペランドを評価します。乗算演算子で同様の動作を実現したい。
.netでは&&
、演算子を直接オーバーロードすることはできませんが&
、false
演算子をオーバーロードできるため、拡張ポイントを使用して短絡演算子の動作を変更できます。詳細については、この記事C# operator overloading: the '&&' operatorを参照してください。
乗算演算子に対してこれまたは同様の動作を実現する手段はありますか?
実装は非常に単純であるため、これは純粋な構文の問題です。次の方法は、機能面で私が望むものを正確に実現します:
public static double ShortCircuitMultiply(double val, Func<double> anotherValue)
{
var epsilon = 0.00000001;
return Math.Abs(val) < epsilon ? 0 : val * anotherValue();
}
注: この実装は完全ではありません。C#では、 or で乗算0.0
すると
が得られますが、- に関してはゼロのみです。この詳細は無視しましょう。私のドメインではまったく関係ありません。Double.NaN
Double.NegativeInfinity
Double.PositiveInfinity
NaN
ShortCircuitMultiply
したがって、ShortCircuitMultiply(0.0, longOperation)
where longOperation
isとして呼び出すとFunc<double>
、最後の項は評価されず、操作の結果は事実上ゼロになります。
問題は、既に述べたように、多くのShortCircuitMultiply
呼び出しがあり、コードをより読みやすくしたいということです。0.0 * longOperation()
可能であれば、コードを次のようにしたいと考えています。
double
別のメモ: ラッパーを構築し、暗黙の二重キャストとオーバーロード*
演算子を作成しようとしました。これはおそらく冗長であることを理解しています。読みやすさを実現したかったのですが、さらに別のラッパーを構築しようとしています。とにかく、次のコードは私の意図を示しています。
class MyDouble
{
double value;
public MyDouble(double value)
{
this.value = value;
}
public static MyDouble operator *(MyDouble left, MyDouble right)
{
Console.WriteLine ("* operator call");
return new MyDouble(left.value * right.value);
}
public static implicit operator double(MyDouble myDouble)
{
Console.WriteLine ("cast to double");
return myDouble.value;
}
public static implicit operator MyDouble(double value)
{
Console.WriteLine ("cast to MyDouble");
return new MyDouble(value);
}
}
今私が行くなら:
MyDouble zero = 0;
Console.WriteLine (zero * longOperation()); //longOperation is still Func<double>
私は受け取りました:
cast to MyDouble
called longOperation <-- want to avoid this (it's printed from longOperation body)
cast to double
cast to MyDouble
* operator call
cast to double
0
しかし、ご覧のとおり、longOperation
オーバーロードされた演算子が呼び出されるずっと前に評価され、パラメーターの 1 つを代用したり、遅延させFunc
たりすることはできません。Expression