4

私はクラスを持っています:

public class ClassA<T>
{
  public T Value {get; set;}
  public string Description {get; set;}
}

ただし、ClassA は任意の型の値を持つことができます。型の値に関係なく、ClassA の他のプロパティを設定できる必要があります。だから私は方法を持っています:

public void DoWork(ClassA<object> source, ClassA<object> destination)
{
  destination.Description = source.Description;
}

ただし、これを実行しようとすると、次のようなランタイム エラーが発生しますClassA<DateTime>ClassA<object>

私は何でもオブジェクトとして渡すことができると思っていました...私は似たようなものをウェブ全体で探しました.キーワードを正しく取得していないだけかもしれません.

誰にも提案はありますか?

ありがとう

4

4 に答える 4

4

さまざまなジェネリック型を使用できるようにする必要がある場合は、パラメーターごとに異なる型を指定できます。

public void Work<TSource, TDestination>(ClassA<TSource> source, ClassA<TDestination> destination)
{
    destination.Description = source.Description;
}

ただし、ここでの本当の問題は、ジェネリッククラスに共通のプロパティがあることです。たとえば、共通のインターフェイスを使用してジェネリック部分を削除できます。

public interface IClassA
{
    string Description { get; set; }
}

public class ClassA<T> : IClassA
{
    ...
}

public void DoWork(IClassA source, IClassA destination)
{
    destination.Description = source.Description;
}
于 2012-12-14T15:19:02.603 に答える
4

あなたはそれをすることができません。

ClassA<int>aを受け入れるメソッドに a を渡すことができればClassA<object> wrapper、そのメソッドは を呼び出すことができますwrapper.Value = "not an integer";。ではどうすればよいのでしょうか。整数のみを保持できるオブジェクトに文字列を設定しました。コンパイラは、指定できるものを強制できないことを認識しているため、そもそもオブジェクトを渡すことができません。

実際の解決策としては、2 つ思い浮かびます。

オプションである場合は、メソッドをジェネリックにすることができます。

public void DoWork<TSource, TDestination>(ClassA<TSource> source, ClassA<TDestination> destination)
{
  destination.Description = source.Description;
}

または、共変インターフェイスを作成できます。

public interface IWrapper<out T>
{
    T Value {get;}
    string Description {get;set;}
}

public class ClassA<T> : IWrapper<T>
{
    //...
}

public void DoWork(IWrapper<object> source, IWrapper<object> destination)
{
  destination.Description = source.Description;
}

あなたのDoWorkメソッドでは、実際には を使用することさえないValueので、インターフェースを非ジェネリック、非共変にして、単に を削除することができますValue。ここでの利点は、そのインターフェイスを使用しClassAて、共通の基本型を持つ任意の数のオブジェクトの値プロパティにアクセスできることです。

于 2012-12-14T15:16:07.617 に答える
2

これは、拡張メソッドとはまったく関係ありません。それは一般的な分散と関係があります。次のように見るのが最も簡単です。

ClassA<DateTime> x = new ClassA<DateTime>();
ClassA<Object> y = x;

これは、同じ方法でコンパイルに失敗します。

C# 4 の時点では、ジェネリック バリアンスのサポートは限定されていますが、次のようになります。

  • インターフェイスとデリゲートのみ
  • 参照型のみ
  • 明示的に宣言された場所のみ

詳細については、 MSDNを参照するか、Eric Lippert のブログ投稿 を参照してください。

それが機能しない理由を説明しています。それを修正する方法については、ジェイソンの答えに従って拡張メソッドを汎用にすることがおそらく最も簡単な方法です。

現時点では、拡張メソッドすら持っていないことに注意してください。次のように、最上位の非ジェネリック静的クラスで宣言する必要があります。

public static void DoWork<T>(this ClassA<T> source, ClassA<T> destination)
{
    destination.Description = source.Description;
}
于 2012-12-14T15:15:38.093 に答える
0

私はあなたがこれを意味すると仮定します:

public void DoWork<T>(ClassA<T> source, ClassA<T> destination)
{
  destination.Description = source.Description;
}
于 2012-12-14T15:11:43.627 に答える