9

非ジェネリックメソッドはそれを含むクラスのジェネリックメンバーにアクセスし、とにかくジェネリック引数を渡すことができるので、なぜ/いつジェネリックメソッドを使用したいのかについて少し混乱しています。

したがって、要点を見逃している可能性が高い缶詰の例を使用して(それでも、なぜ私がこの質問をしているのかを強調しています)、なぜ私はこれを行うのでしょうか?

public class SomeGeneric<T>
{
    public T Swap<T>(ref T a, ref T b)
    {
        T tmp = a;
        a = b;
        b = tmp;
    }
}

以上

public class SomeGeneric<T>
{
    public T Swap(ref T a, ref T b)
    {
        T tmp = a;
        a = b;
        b = tmp;
    }
}

これ?

または、実際には、なぜジェネリックメソッドを使用したいのですか?

4

6 に答える 6

9

通常、ジェネリックではない型ではジェネリックメソッドを使用します。

たとえば、Enumerableクラスを見てください。これは、ほとんどのLINQ機能の汎用拡張メソッドを定義しますが、それ自体は汎用ではありません。

また、ジェネリック型内にジェネリックメソッドが必要な場合もありますが、ジェネリックメソッドが別のジェネリック型指定子を使用した場合に限ります。

これにより、次のようなものを書くことができます。

 class Foo<T> where T : IConvertible, IComparable<T>
 {
      int CompareTo<U>(U other) where U : IConvertible
      {
           // Convert to this
           T otherConverted = Convert.ChangeType(other, typeof(T));
           return this.CompareTo(otherConverted);
      }
 }

(確かに、これは少し工夫されていますが、コンパイルして正しく動作し、などFoo<int>と比較できますdouble

于 2012-12-19T19:10:03.160 に答える
4

含まれているクラスがジェネリックでない場合はどうなりますか?ジェネリック型のパラメーターが異なる場合はどうなりますか?

于 2012-12-19T19:09:53.930 に答える
2

クラスパラメータが使用されていないため、最初の例はあまり意味がありません。ただし、別の例を考えてみましょう。

public class SomeGeneric<T>
{
    public K ConvertTo<T>(T a)
    {
         return CodeThatConvertsTtoK(a);
    }
}

とその使用法: new SomeGeneric<int>().ConvertToInt("ten");

于 2012-12-19T19:14:08.873 に答える
1

クラスとメソッドの両方がジェネリックである場合、もちろん、型パラメーター(「ジェネリックパラメーター」)は異なる名前を持っている必要があります。T最初の例のように、2つの異なる名前を付けることはできません。

メソッドが非静的である場合(見たところ)、包含クラスを汎用にすることを選択した場合、クラスをインスタンス化するときにタイプをすでに指定する必要があります。のようにvar obj = new SomeGeneric<DateTime>();。したがって、クラスによってモデル化されたオブジェクトに論理的に「属する」ものである必要があります。

メソッドが静的であり、クラスを汎用にすることを選択した場合でも、何らかの方法でクラスと一緒にtypeパラメーターを指定する必要があります。メソッドがクラスの外部から呼び出された場合、次のようになりSomeGeneric<DateTime>.Swap(ref a, ref b);ます。

メソッドをジェネリックにすることの利点は、多くの場合、型推論を使用できることです。これにより、山括弧で囲まれた型パラメーターを省略できます。これは、ジェネリックメソッドでのみ実行できます。例:メソッドが汎用nonGeneric.Swap(ref a, ref b);である場合。Swap<T>コンパイラは、とのコンパイル時の型を調べて、a指定しなくても、bどれがT適合するかを判断します。

結論:Tが(のように)論理的にクラスに属していない場合はList<T>、メソッドとともに配置します。

于 2012-12-19T20:23:02.340 に答える
0

メソッドレベルの型パラメーターの一般的なシナリオは、非ジェネリック静的クラスで宣言する必要があるため、拡張メソッドです。ただし、非ジェネリック型のすべてのジェネリックメンバーに必要です。

public static class Extensions
{
    public static void Foo<A, B>(this A a, B b) { [...] }

    public static T Bar<T>(this String input) { [...] }

    public static U FooBar<V, W>(this V v, W w) { [...] }
}
于 2012-12-19T19:14:26.513 に答える
0

これは、ジェネリックメソッドが本当に優れている1つの例です。1+2二分木として表現されるような表現を考えてみましょう。ツリー全体にVisitorパターンを実装し、ある種のmap/reduce操作を目標とします。いくつかの例は次のとおりです。

  • 式をaに縮小stringして印刷します
  • 式をaに還元して、doubleその値を計算します
  • 一部のメンバーが変更/追加/削除された式を別の式にマッピングする

これらの操作はすべて、Visitorパターンメソッドの背後に置くことができます。

public abstract class Expression
{
  public abstract T Reduce<T>(ITransformer<T> transformer);
}

これは従来のVisitorの実装に似ていますが、用語が変更されています。のReduce()代わりにAccept()、のITransformer<T>代わりにがありIVisitorます。メソッドが汎用であることに注意してください。

このアプローチによりITransformer<T>、階層を任意のタイプTに変換する任意の数のクラスを作成し、map-reduce操作をサポートできます。

于 2021-09-07T21:55:48.460 に答える