2012-04-09 3 views
6

は、私はこのようなインターフェイスを持っている:C#のインターフェイスにType Tを返すには?

public interface IUser{ 
    //some properties here 

    T ToDerived(User u); 
} 

は、私が開発をインタフェースする新たなんだので、ここで私が達成しようとしているものです。私はベースクラスを持っています

public class User 

上記のインターフェイスを実装していません。それから私はSalesUserクラスの派生クラスIはToDerivedのための関数を記述したいと思い

SalesUser : User, IUser 
{ 
    //no properties needed because they exist in the User class 

    SalesUser ToDerived(User u) 
    { 
     //code for converting a base User to a derived SalesUser 
    } 
} 

(ユーザU)を持つことになりますが、インターフェイスに、私はToDerivedメソッドの宣言としてこれを定義する方法がわかりません私が今インターフェイスに入れているのはコンパイルされていません。

これは意味があると思います。

+1

[ここ](http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser)aspx)は、この質問に関連するEricのブログへのリンクです。これには、以下の回答によく似た例と、この設計メカニズムを使用することの落とし穴の両方が含まれます。 – Servy

答えて

14
public interface IUser<T> where T : User 
{ 
    //some properties here 

    T ToDerived(User u); 
} 

SalesUser : User, IUser<SalesUser> 
{ 
    //no properties needed because they exist in the User class 

    SalesUser ToDerived(User u) 
    { 
     //code for converting a base User to a derived SalesUser 
    } 
} 

わからないこれが何をしたいですが、私はジェネリック型がUserであるか、それを継承することを確実にするためのインターフェイスでジェネリック型の制約を追加しました。

+0

私にそれを打つが、私は 'どこにT:User'を追加するだろう。 –

+0

@JimSchubert - あなたがコメントしている間にそれを考慮して追加しました;) – Oded

+0

あなたは2度私にそれを打ちました:( –

0

インターフェイスはクラスとそのメンバーを実装なしで定義することを忘れないでください。インターフェイスを作成できますが、インターフェイスには実装クラスが必要です。

+0

これはどのように答えるのですか? – Oded

+0

私はToDerived(User u)の関数をSalesUserクラスに記述したいと思いますが、インタフェースではこれをToDerivedメソッド宣言として定義する方法がわかりません。間違っているかどうかわかりません。 –

3

Odedの答えは、コンパイルの問題を解決し、インターフェイスを満たすToDerivedメソッドを定義できるようにします。しかし、私がコメントで述べたように、私はこれが最良の実装であるとは確信していません。

私が持っている主な問題は、このような変換方法は通常、静的なコンテキストで必要となることです。 SalesUserのインスタンスがありません。あなたは1つを持ち、Userを持っているので、静的コンテキスト(SalesUser.ToDerived(myUser))でメソッドを呼び出し、SalesUserを取得します(このメソッドはFromUser()などと呼ばれます)。インターフェイスで指定する方法では、ユーザーをSalesUserに変換するためにSalesUserが既に必要です。既存のSalesUserが本当に必要になると思う唯一の状況は、「部分クローン」です。メソッドを呼び出すSalesUserに渡されたUserとSalesUserから渡されたUserの両方の情報を使用して、新しいSalesUserインスタンスを作成しています。他のすべてのケースでは、SalesUser(前述のように静的でなければならないコンバージョン)を必要としないか、またはUser(「クローン」または「ディープコピー」メソッドを使用する必要はありません。メソッドを呼び出したインスタンスと同じデータ)。

また、クラスのコンシューマは、ユーザーからSalesUserへの変換を実行するためにToDerived()を呼び出す必要があることを知る必要があります。

public class SalesUser 
{ 

    public static explicit operator (User user) 
    { 
     //perform conversion of User to SalesUser 
    } 

} 

//the above operator permits the following: 
mySalesUser = (SalesUser)myUser; 

... OR、変換演算子を失敗し、1ユーザーを使用してSalesUserを構築できることを期待しています:通常、C#のプログラマは、明示的または暗黙的な変換が利用可能であることを期待する

public class SalesUser:IUser 
{ 
    public SalesUser(User user) 
    { 
     //initialize this instance using the User object 
    } 
} 

//the above allows you to do this: 
mySalesUser = new SalesUser(myUser); 

//and it also allows the definition of a method like this, 
//which requires the generic to be an IUser and also requires a constructor with a User 
public void DoSomethingWithIUser<T>(User myUser) where T:IUser, new(User) 
{ 
    //...which would allow you to perform the "conversion" by creating a T: 
    var myT = new T(myUser); 
} 

静的メンバーはインターフェイス定義を満たさず、インターフェイスは静的メンバーまたはコンストラクタシグネチャを定義できません。これはIUserインターフェイスが変換メソッドを定義しようとすべきではないことを私に伝えます。その代わりに、ある種のIUserを必要とするメソッドはそれを指定するだけで、ユーザーはそれが自分自身に変換できることを知る必要のない実装を必要に応じて提供することができます。

+0

あなたが正しいです、Odedは問題を解決し、私が探していた正確な方法で私の質問に答えました。しかし、私はあなたの説明が好きで、この特定の方法は一般的に静的な方法であるので、私はこのデザインパターンを使用すべきではありません(私はこれに同意します)。 あなたのサンプルをビルドしようとすると、基本Userクラスを継承するにはSalesUserクラスが必要であることに注意してください。 パブリッククラスSalesUser:User、IUser これを実行しようとすると、明示的なメソッドは機能しません。 "基本クラスとの間でのユーザー定義の変換は許可されていません。" – jaressloo

+0

コンストラクタベースの「変換」は引き続き機能するはずです。 – KeithS

+0

ええ、コンストラクタベースのバージョンは、今のところ取ることを選んだルートです。ベースユーザーから派生したSalesUserへの明示的な変換を許可するために、もう一方の方法を見つけようとします。ご協力いただきありがとうございます。 – jaressloo

関連する問題