2017-02-21 3 views
19

はじめことなく、複数の==演算子のオーバーロード:
私は同じ仕事をいくつかのクラスを持っていますが、異なる値の型を持つ(フロートや整数の例えばベクトル)。
今、私は平等をチェックできるようにしたいと考えています。この平等は型間でも働くべきです(vectorF == vectorIなど)。
また、ヌルチェック(vectorF == null)も可能である必要があります。C#の、あいまいなヌルチェック

アプローチ:!
私のアプローチは、複数の==のためのオーバーロードと=演算子、各可能な組み合わせのための1つを作成することです。

public sealed class VectorF 
{ 
    [...] 

    public static bool operator == (VectorF left, VectorI right) 
    { 
     // Implementation... 
    } 

    public static bool operator == (VectorF left, VectorF right) 
    { 
     // Implementation... 
    } 

    // Same for != operator 
    [...] 
} 

問題:複数のオーバーロードを使用して
呼び出しがあいまいになるとして、私は、==演算子とはnullチェックを行うことはできません。

var v = new VectorF([...]); 

if (v == null) // This call is ambiguous 
[...] 

代わりにReferenceEqualsまたはnullのキャストを使用する可能性があることに気付いていますが、そのアプローチは深刻な制限です。

var v = new VectorF([...]); 

if(object.ReferenceEquals(v, null)) // Would work, is not user friendly. 
[...] 

if(v == (VectorF)null) // Would also work, is neither user friendly. 
[...] 

質問
は、それが普通のNULLチェックを可能にし、異なるベクトル間の等価性チェックを可能にすること、のように==演算子を実装するためにそこに方法は何ですか?

また、これを実装する方法も実装する方法もありますか?

+5

あなたのVectorクラスは本当に不変な構造体であるはずです。そして、「ヌル」の問題は生じない。 (あなたのクラスには2つまたは3つの値しか入っていないと仮定しています) –

+2

[zugzwang](https://en.wikipedia.org/wiki/Zugzwang)のように聞こえます:good = ''=='または '== null '。他の型のベクトルと比較する方法はありますか?例えば。 'VectorF。IsSame(VectorI) '?コンパイラは 'vectorF == vectorI'を試みるとユーザの間違いを表示し、ユーザは比較するメソッドを探します。別のこと: 'float'と' int'を比較することは正確ではありません。最初に 'VectorF'を' VectorI'にキャストし、次に 'VectorI'を比較するのはどうですか? – Sinatr

+0

なぜ左URTが必要なのですか?私はあなたに私たちが過負荷のメソッドの内容を共有することができますか? – levent

答えて

20

:私はこのような場合には、それは==演算子をオーバーロードし、代わりのようなものを行うにはないだろう何

+0

ありがとうございます。あなたは正しいですが、==は参照平等でなければなりません。呼び出しをできるだけ最適化したかったので、私は暗黙の変換は考えていませんでした。しかし、値がとにかく変換​​されるので、結局大きな違いはありません。 – Chillersanim

8

あなたはisを使用して比較を中心に回すことができます。

if (v is VectorF) 

vnullある場合は、このチェックは失敗します。私はそもそもデザイン全体に押し戻したい

public static bool operator == (VectorF left, object right) { 
    if (object.ReferenceEquals(null, right)) { 
     // handle null case 
    } 
    VectorF rightF = right as VectorF; 
    if (!object.ReferenceEquals(null, rightF)) { 
     // Compare VectorF 
    } 
    VectorI rightI = right as VectorI; 
    if (!object.ReferenceEquals(null, rightI)) { 
     // Compare VectorI 
    } 
    // and so on... 
} 
+0

本当に良い解決策です。 –

+5

私はこの解決策が嫌いです。あなたが実際にやっていることのセマンティクスは、「巧妙な」トリックで隠されています。このコードを読んで、あなたが「ヌル」をチェックしていることは明らかではありません。正直です。 – InBetween

+1

さて、 'is'(または' as')を使ってタイプチェックするのはよくあることですが、誰もがヌルチェックをしているわけではありません。 'null'は特定の型ではないことがかなり分かりました。 –

2

。私は==の値のセマンティクスを異なるタイプ間で実装することはありませんが、私はそれがむしろ混乱していると思います。instaceTypedA == instanceTypedB(少なくとも私にとって)

この機能が必要な場合は、VectorIVectorFの間の暗黙的な変換を実装します。これがフレームワークの仕組みです。次の操作を行うとき:

int i = 1; 
double d = 1; 
var b = i == d; 

oveload ==(int, double)は魔法のように作られていません。何が起こるかは、iが暗黙的にdoubleに変換され、==(double, double)が呼び出されるということです。

+2

Ewww、コンパイル時の型安全性を犠牲にして、ヌルチェックを繰り返さないでください。 –

関連する問題