编程语言
首页 > 编程语言> > [Professional C# 7] GENERIC METHODS (泛型方法)

[Professional C# 7] GENERIC METHODS (泛型方法)

作者:互联网

Generic Methods Example

public class Account
{
  public string Name { get; }
  public decimal Balance { get; }
  public Account(string name, Decimal balance)
  {
    Name = name;
    Balance = balance;
  }
}
public static class Algorithms
{
  public static decimal AccumulateSimple(IEnumerable<Account> source)
  {
    decimal sum = 0;
    foreach (Account a in source)
    {
      sum += a.Balance;
    }
    return sum;
  }
}

The AccumulateSimple method is invoked like this:

decimal amount = Algorithms.AccumulateSimple(accounts);

Generic Methods with Constraints

The second version of the Accumulate method accepts any type that implements the interface IAccount. 

public static decimal Accumulate<TAccount>(IEnumerable<TAccount> source)
  where TAccount: IAccount
{
  decimal sum = 0;
  foreach (TAccount a in source)
  {
    sum += a.Balance;
  }
  return sum;
}

The new Accumulate method can be invoked by defining the Account type as a generic type parameter 

decimal amount = Algorithm.Accumulate<Account>(accounts);

Because the generic type parameter can be automatically inferred by the compiler from the parameter type
of the method, it is valid to invoke the Accumulate method this way:

decimal amount = Algorithm.Accumulate(accounts);

Generic Methods with Delegates

public static T2 Accumulate<T1, T2>(IEnumerable<T1> source,
  Func<T1, T2, T2> action)
{
  T2 sum = default(T2);
  foreach (T1 item in source)
  {
    sum = action(item, sum);
  }
  return sum;
}

In calling this method, it is necessary to specify the generic parameter types because the compiler cannot infer this automatically.

decimal amount = Algorithm.Accumulate<Account, decimal>(
accounts, (item, sum) => sum += item.Balance);

Generic Methods Specialization

public class MethodOverloads
{
  public void Foo<T>(T obj) =>Console.WriteLine($"Foo<T>(T obj), obj type: {obj.GetType().Name}");

  public void Foo(int x) =>Console.WriteLine("Foo(int x)");

  public void Foo<T1, T2>(T1 obj1, T2 obj2) =>
    Console.WriteLine($"Foo<T1, T2>(T1 obj1, T2 obj2); " + 
      $"{obj1.GetType().Name} {obj2.GetType().Name}");

  public void Foo<T>(int obj1, T obj2) =>Console.WriteLine($"Foo<T>(int obj1, T obj2); {obj2.GetType().Name}");

  public void Bar<T>(T obj) => Foo(obj);
}

If an int is passed, then the method with the int parameter is selected. With any other parameter type, the compiler chooses the generic version of the method.

static void Main()
{
  var test = new MethodOverloads();
  test.Foo(33);
  test.Foo("abc");
  test.Foo("abc", 42);
  test.Foo(33, "abc");
}

Running the program, you can see by the output that the method with the best match is taken:

Foo(int x)
Foo<T>(T obj), obj type: String
Foo<T1, T2>(T1 obj1, T2 obj2); String Int32
Foo<T>(int obj1, T obj2); String

 

标签:obj2,METHODS,decimal,C#,sum,method,GENERIC,Foo,public
来源: https://www.cnblogs.com/FH-cnblogs/p/16546553.html