2009-06-09 10 views
7

ここで間違っていることはわかりません。私は、文字列から特定の文字列のためにいくつかのメソッドは、書式設定と、同様に/に、基本的に見せかけ整数であるジェネリッククラスを、持っているとの変換をint型:暗黙的/明示的変換メソッドはC#で継承されていますか?

public class Base 
{ 
    protected int m_value; 
    ... 
    // From int 
    public static implicit operator Base(int Value) 
    { 
     return new Base(Value); 
    } 
    ... 
    // To string 
    public static explicit operator string(Base Value) 
    { 
     return String.Format("${0:X6}", (int)Value); 
    } 
} 

そして、それは細かい機能します。私は正常に暗黙的および明示的な変換を使用することができます。

Base b = 1; 
Console.WriteLine((string)b); // Outputs "$000001", as expected. 

は、その後、私は、このクラスからm_valueに/オフ異なるという名前のビットをオンに異なる子クラスを、派生します。たとえば、次のように

public class Derived : Base 
{ 

} 

そして私はに/変換int型から私の暗黙的に使用することはできません。

Derived d = 3; 
// Cannot implicitly convert type 'int' to 'Derived'. An explicit conversion exists (are you missing a cast?) 

はこれでも同じエラーを与える:

Derived d = (int)3; 

は暗黙的/明示的な変換です派生クラスで継承されない?そうしなければ多くのコードをコピーする必要があります。

応答すみません、ありがとうございました!あなたはすべて「回答」チェックマークに値します。彼らはすべて非常に良い答えです。鍵は、等号の両側の型について考えることです。今私はそういうことを考えている、それは完璧な意味合いがある。

私は明らかに「派生した」コンバージョンを書き直すだけです。 "Int32、Stringなどへの変換"の変換は引き続き適用されます。

+1

このすべての仕組みの微妙な点の詳細については、件名に関する記事を参照してください。http://blogs.msdn.com/ericlippert/archive/2007/04/16 /chained-user-defined-explicit-conversions-in-c.aspx –

答えて

6

Derived d = (int)3; 

が動作しない理由があります。コードnew Derived(...)を含む変換演算子を提供していないので、新しいDerivedインスタンスをこのようにすることはできません。(これは継承が原因staticキーワードに本当にありませんが、それは、「継承」しているかのように)

注意、しかし、逆変換

Derived v = ...; 
string s = (string)v; 

が正常に動作すること。

+1

OPの希望する動作を得る方法がないと思いますか? – weberc2

3

いいえ、それはそのようには動作しません。コンパイラはを暗黙的ににダウンキャストしてベースから派生します。基本的に、あなたはそれがあなたのための暗黙のアップキャストを行いますので、あなたは、あなたの文字列のキャストから、あなたのベースクラスのimplmentationsを取得します...

D d = new B(); 

を行うことはできません。

(あなたの派生クラスがDと呼ばれていると仮定)のようなあなたは、整数の拡張機能を使用して派生クラスにあなたのメソッドをコピーしたくなかった場合は、周りの作業を行うことができます...

public static class Ext 
{ 
    public static D IntAsD(this int val) 
    { 
     return new D(val); 
    } 
} 

はその後、あなたは確かに

D d1 = 5.IntAsD(); 

...で欲しい何ができるか、それは完璧ではないのですが、それはあなたのニーズに合うかもしれません。このオペレータを呼び出すために必要とされるタイプDerivedが正確オペレータBaseの戻り値と一致しないため

2

オーバーロードされた演算子(コンバージョンを含む)は継承されていますが、期待通りの方法ではありません。特に、派生型で動作するように魔法的に拡張されているわけではありません。

Derived d = 3; 

この時点で、コンパイラには2つのクラスSystem.Int32とDerivedがあります。そこで、これらのクラスの変換演算子を探します。 BaseからDerivedによって継承されたもの、すなわち:

引数がInt32である必要があるため、2番目の値は一致しません。最初の引数は引数と一致しますが、戻り値の型はBaseであり、それが一致しません。 Baseの明示的な演算子が存在し、適用されるので、(引数は、ベースであることが予想基地から派生継承するため、引数の型と一致している、

string s = (string) new Derived(); 

そして、それは動作します:一方、あなたはこれを書くことができます)。

派生型の「正しく」変換演算子をコンパイラが自動的に再定義しない理由は、そうする一般的な方法がないためです。

0

いいえ、そうではありません。ここで手がかりです:C#で

public **static** implicit operator Base(int Value)

静的メソッドは、プライベートクラスメンバーへのアクセス権を持つだけのグローバル関数です。彼らは決して継承されません

+3

静的メソッドが継承されないことは間違いありませんが、この質問には完全には関係ありません。 C#3.0仕様の関連するセクションは6.4節です。3では、静的演算子を検索する型を記述します。「この集合は、ソース・タイプとその基本クラス、およびターゲット・タイプとその基本クラスで構成されます。 –

+1

oops。私は間違った答えを削除するだろうが、あなたのコメントは保つ価値があるので、私は悪く見えるようにそこに滞在する必要があります:-) –

1

変換/演算子メソッドは便利ですが、他の人が指摘しているように、彼らはいつもあなたが望むことをするつもりはありません。特に、コンパイラが=記号の両側に正しい型を見ない場合、変換/演算子は考慮されません。

object str = "hello"; 
if (str == "hello") { 
} 

はさらに、カスタム変換は/キーワードであるとして使用する場合に考慮されていません。あなたが行う場合は、次はあなたがコンパイラの警告を受ける理由です。

明示的/暗黙的な変換を実装する場合は、IConvertibleの実装やTypeConverterの実装も検討する必要があります。これにより、基本クラスで型変換を処理する際の柔軟性が向上します。

0

これを直接行うことはできませんが、コードを再利用できるようにするためのショートカットがあります。

public class Base 
{ 
    protected int m_value; 
    ... 
    // From int 
    public static implicit operator Base(int Value) 
    { 
     Base newObject = new Base(); 
     newObject.FromInt(Value); 
     return newObject; 
    } 
    ... 
    // To string 
    public static explicit operator string(Base Value) 
    { 
     return String.Format("${0:X6}", (int)Value); 
    } 

    //Instance FromInt() 
    protected void FromInt(int value) 
    { 
     m_value = value; 
    } 
} 

public class Derived : Base 
{ 
    // To string, re-use Base-ToString 
    public static explicit operator string(Derived Value) 
    { 
     // Cast (Derived)Value to (Base)Value and use implemented (Base)toString 
     return (string)(Base)Value; 
    } 

    // Use FromInt, which has access to instance variables 
    public static implicit operator Base(int Value) 
    { 
     // We can't use (Base)obj = Value because it will create 
     // a "new Base()" not a "new Derived()" 
     Derived newObject = new Derived(); 
     newObject.FromInt(Value); 
     return newObject; 
    } 
} 
関連する問題