2012-02-29 7 views
6

関連質問:Accessing a Class property without using dot operator私はMyDoubleというクラスを作成しましたInt64型への私のクラス、ダブルなどを鋳造

は私がMyDouble上の操作のすべての種類を行うことができています。この

class MyDouble 
{ 
    double value; 
    //overloaded operators and methods 
} 

のように見えます。例:

MyDouble a = 5.0; 
a += 3.0; 
...etc 

しかし、これはまだエラー、私はそのような(Int64)aのような操作が自動的に(Int64)a.valueに変換することを定義することができますどのように

MyDouble a = 5.0; 
long b = (Int64)a; //error 
long b = (int64)a.value; //works 

を投げますか?ユーザーがvalueプロパティの存在を心配する必要はありません。

+0

なぜ、「long」と「Int64」の両方を使用していますか? 1つは別のもののためのaloasであり、私は、より多くの慣用的な方法が型名の代わりに存在するなら、エイリアスを使用することだと思います。 – Joey

答えて

9

この変換が機能するには、Int64にexplicit conversionが必要です。

これは次のようになります。Int64型のではなく、自分のクラスからInt64型二重から明示的な変換があります

class MyDouble 
{ 
    double value; 

    public static explicit operator Int64(MyDouble value) 
    { 
     return (Int64)value.value; 
    } 
} 
+0

完璧、ありがとう。 – xbonez

+0

なぜそれは明白でなければならないのでしょうか?暗黙の変換も同様に機能し、キャストはオプションになります。 – Jay

+0

@ Jay暗黙の操作を行うことはできますが、変換演算子を含むOPが表示されます。個人的には、私は暗黙のコンバージョンを避けようとする傾向があります。(暗黙的に2倍から長いへの変換は悪い考えですが) –

1

。あなたがする必要があるのは、1つを定義することだけです。あなたのクラスから二重への変換があれば、これを行うことができます:

long x =(long)(double)a;

しかし、それは面倒です。明示的な変換演算子を定義します。

明示的にする理由がない限り、変換は明示的で暗黙的ではありません。

変換によって情報が失われる可能性があるため、言語定義のdoubleからlongへの変換は明示的にです。この変換では、0.5、などの倍数が正確にlongに変換されないため、情報が失われる可能性があります。これは、変換の絞り込みと呼ばれます。

言語定義のコンバージョンでは、コンバージョンの絞り込みは明示的です。それらが暗黙的であった場合、あるタイプの値を別のタイプの変数に割り当てることによって、プログラマーは誤って情報を失う可能性があります。この変換を暗黙的に定義することは、完全に合理的な原則に違反するため、そうするためには説得力のあるケースが必要です。

この原則の価値を示す例です。狭い変換が暗黙のうちに行われると、コードがより脆くなります。 double-to-int変換が暗黙的であると仮定します。

class Family 
{ 
    ICollection<Person> Children { get; set; } 
} 

int GetAverageNumberOfChildren(IEnumerable<Family> families) 
{ 
    return families.Sum(f => f.Children.Count)/families.Count(); 
} 

void SomeMethod(IEnumerable<Family> families) 
{ 
    int averageNumberOfChildren = GetAverageNumberOfChildren(families); 
    //... 
} 

バグがあります! GetAverageNumberOfChildrenはダブルを返す必要があります!それを修正しよう!

double GetAverageNumberOfChildren(IEnumerable<Family> families) 
{ 
    return families.Average(f => f.Children.Count); 
} 

すべてがコンパイルされて実行されます。確かに私たちはそのバグをキャッチしてうれしい!

しかし、悲しいことに、 まだバグがあります!SomeMethodはdoubleをintに暗黙的に変換するため、期待値が2.4である場合、実際の値は2です。

double-to-int変換は明示的であるため、コンパイラは私たち自身から私たちを保存します。 GetAverageNumberOfChildrenを修正した後、は、誤ったプログラムがコンパイルされません。あなたのMyDoubleクラスと同じかlongの範囲よりも小さい範囲で値を整数にそれを制限されたいくつかの検証を持っていた場合

さて、あなたは変換が暗黙的にするためにも安全でしょう。しかし、その場合は、longを使用してください(doubleではなく)。

1

暗黙的な変換と明示的な変換が機能します。

long b = (Int64) a; 

か、単に

long b = a; 

これは単なる変換は、明示的である必要はないことを示すためにある:あなたが行うことができる場所ではこれにより

public static implicit operator long(MyDouble m) 
{ 
    return (long) m.value; 
} 

。ただし、データ損失の可能性があるため、前述のように、にする必要があります。

+0

これは本当ですが、危険です。説明については私の編集した答えを見てください。 – phoog

+0

@phoog私は理解しています。私は「あなたが必要*明示的な変換が必要です」という言葉だけで問題を抱えていました。 – Jay

+0

十分に公正。私は、暗黙的な変換の存在について議論している場合は、変換を狭める理由を明確にすることをお勧めします。そうしなければ、バグの多いプログラムを作成する可能性を考慮せずに、暗黙の変換「明快」または「自分のコードがきれいになるため」を明示的に実装したいと思うかもしれません。 – phoog