views:

575

answers:

3

In C++ templates, one can specify that a certain type parameter is a default. I.e. unless explicitly specified, it will use type T.

Can this be done or approximated in C#?

I'm looking for something like:

public class MyTemplate<T1, T2=string> {}

So that an instance of the type that doesn't explicitly specify T2:

MyTemplate<int> t = new MyTemplate<int>();

Would be essentially:

MyTemplate<int, string> t = new MyTemplate<int, string>();

Ultimately I am looking at a case wherein there is a template that is fairly widely used, but I am considering expanding with an additional type parameter. I could subclass, I guess, but I was curious if there were other options in this vein.

+7  A: 

Subclassing is the best option.

I would subclass your main generic class:

class BaseGeneric<T,U>

with a specific class

class MyGeneric<T> : BaseGeneric<T, string>

This makes it easy to keep your logic in one place (the base class), but also easy to provide both usage options. Depending on the class, there is probably very little extra work needed to make this happen.

Reed Copsey
ah...that makes sense. Is the type name allowed to be the same if the type parameters provide a unique signature?
ee
@ee: yes, generics are `overloadable` by parameter count.
Mehrdad Afshari
@ee: Yes, but I would be wary of doing that. It is "legal" in .NET to do so, but it can lead to confusion. I would rather have the string derived type's name be similar to the main generic class (so it's obvious what it is/easy to find), but a name that makes it obvious that it's a string.
Reed Copsey
@Reed: Does it really lead to confusion? For this specific case, I think having the same name even helps. There are examples in .NET that do the same thing: Func<> delegate for instance.
Mehrdad Afshari
I can see it both ways. If you expected overloaded versions to be equally used, I think I would use the same type name. If it were that the underlying base was rarely used but for special circumstances, I think choosing a name that portraits that would make sense. Thanks all for the quality answers.
ee
@Mehrdad: It depends on the usage scenario, etc. Func<>/Action<>/etc are a bit different - They aren't providing defaults options with a specific type, but acting more like method overloads since the extra arguments are completely unused. If I wanted a typedef for Func<T,U,string>, I'd rename it.
Reed Copsey
For example, Predicate<T> is just Func<T,bool>, but renamed since it's for a different purpose.
Reed Copsey
+1  A: 

C# does not support such a feature.

As you said, you can subclass it (if it's not sealed, and duplicate all constructor declarations) but it's a completely different thing.

Mehrdad Afshari
+1  A: 

Unfortunately C# does not support what you are trying to do. It would be a difficult feature to implement given that the default type for a parameter would have to adhere to the generic constraints and would most likely create headaches when the CLR tried to ensure type-safety.

Andrew Hare
Not really. It could have been done with an attribute (like default parameters in VB.NET) and have the compiler replace it at compile time. The primary reason is C# design goals.
Mehrdad Afshari
The compiler has to ensure that the default parameter satisfies the generic constraints. Also the default parameter would be a generic constraint itself because any assumptions made about the type parameter in the method would require that any non-default type parameter inherit from it.
Andrew Hare