Reputation: 6042
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
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:
string
to print itdouble
to calculate its valueAll 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
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
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
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
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
Reputation: 161773
What if the containing class is not generic? What if it has different generic type parameters?
Upvotes: 4