Major Productions
Major Productions

Reputation: 6042

C# - generic methods vs. non-generic methods

I'm a bit confused about why/when I'd ever want to use a generic method since a non-generic method can access the generic members of its containing class and be passed generic arguments anyway.

So, using a canned example that likely misses the point (yet highlights why I'm asking this question), why would I do this:

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

over

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

this?

Or, really, why would I want to use a generic method at all?

Upvotes: 9

Views: 6860

Answers (6)

Dmitri Nesteruk
Dmitri Nesteruk

Reputation: 23789

Here's one example where generic methods really shine. Consider an expression such as 1+2 expressed as a binary tree. You want to implement the Visitor pattern on the entire tree, with the goal being some sort of map/reduce operations. Some examples would be:

  • Reducing an expression to a string to print it
  • Reducing an expression to a double to calculate its value
  • Mapping an expression to another expression with some members altered/added/removed

All of these operations can be put behind a Visitor pattern method:

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

This is similar to the classic Visitor implementation, but the terminology is changed: we have Reduce() instead of Accept() and an ITransformer<T> instead of an IVisitor. Notice that the method is generic.

This approach allows us to create any number of ITransformer<T> classes that transform the hierarchy to any type T, supporting map-reduce operations.

Upvotes: 0

Jeppe Stig Nielsen
Jeppe Stig Nielsen

Reputation: 61950

If both the class and the method are generic, the type parameters ("generic parameters") must have different names, of course. There can't be two different things named T like in your first example.

If your method is non-static (as it seems), if you choose to make the containing class generic, the type will have to be specified already when you instantiate your class. Like var obj = new SomeGeneric<DateTime>();. So it should be something that logically "belongs" to the object modelled by the class.

If your method is static, and you choose to make the class generic, you will still have to specify the type parameter together with the class somehow. If the method is called from outside the class, it would go like SomeGeneric<DateTime>.Swap(ref a, ref b);.

The advantage with making the method generic, is that in many cases you can use type inference which allows you to omit the angle bracketed type parameter. You can only do this with generic methods. Example: nonGeneric.Swap(ref a, ref b); where the Swap<T> method is generic. The compiler will look at the compile-time types of a and b and figure out which T fits in, without you specifying it.

Conclusion: If the T does not logically belong to the class (as in List<T>), put it with the method.

Upvotes: 1

Daniel Br&#252;ckner
Daniel Br&#252;ckner

Reputation: 59645

A common scenario for method level type parameters are extension methods because they must be declared in a non-generic static class. But they are required for every generic member in a non-generic type.

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) { [...] }
}

Upvotes: 1

the_joric
the_joric

Reputation: 12226

The first example does not make much sense, because class parameter is not used. Consider another example though:

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

and its usage: new SomeGeneric<int>().ConvertToInt("ten");

Upvotes: 2

Reed Copsey
Reed Copsey

Reputation: 564373

You'd typically use a generic method in a type that isn't generic.

For example, look at the Enumerable class. It defines the generic extension methods for most of the LINQ fucntionaltiy, but itself isn't generic.

You also might want a generic method within a generic type, but only if the generic method used a different generic type specifier.

This lets you write something like the following:

 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);
      }
 }

(Granted, this is a bit contrived, but does compile and work correctly for Foo<int> comparing to a double, etc)

Upvotes: 9

John Saunders
John Saunders

Reputation: 161773

What if the containing class is not generic? What if it has different generic type parameters?

Upvotes: 4

Related Questions