views:

73

answers:

2

I'd like to do something like the following, but because T is essentially just a System.Object this won't work. I know T can be constrained by an interface, but that isn't an option.

public class Vborr<T> where T : struct
  {

    public Vborr()
    {
    public T Next()
    {
      if ( typeof( T ) == typeof( Double ) )
      {
         // do something for doubles
      }
      if ( typeof( T ) == typeof( Float ) )
      {
         // do something different for floats..
      }
    }
  }

I frequently find C# generics lacking.

Thanks!

Paul

+7  A: 

The whole point of generics is that you can do the same thing for any valid type.

If you're truly doing something specific for the types, then the method isn't generic anymore and should be overloaded for each specific type.

public class Vborr<T> where T : struct
{
    public virtual T Next() { // Generic Implementation }
}

public class VborrInt : Vborr<int>
{
    public override int Next() { // Specific to int }
}

public class VborrDouble : Vborr<double>
{
    public override double Next() { // Specific to double }
}
Justin Niessner
+1 That is quite what I was to write.
Will Marcouiller
One can do it as a performance optimization avoiding interface or lambda calls in certain scenarios. For example the Operator class in MiscUtil could profit from this.
CodeInChaos
Yes, good point. But because for my users calling public T Next() the behavior is functionally the same for either Doubles or Floats. They shouldn't have to deal w/ two classes (you can't overload on return types in C#...only in the IL is that possible)
Paul
To address your last point you could create a VborrFactory<T> class that would return the correct subclass to the user, who could view it as Vborr<T> and not care that it actually was a VborrInt, or VborrDouble or whatever.
Steve Ellinger
I'm giving Justin an answer too, because it doesn't hurt to be reminded of this. But, there are special cases where some <T> differentiation is needed as in this case where there are big performance differences between single/double - and that's the users only care.
Paul
+1  A: 

The approach I would take here would be that of a factory pattern and creating specialized instances of Vborr based off of the type. For example

public class Vborr<T> where T : struct {
  protected Vborr() { }
  abstract T Next();
}

public static class VborrFactory { 
  private sealed class VborrFloat : Vborr<float> {
    public VborrFloat() {}
    public override float Next() {
      ...
    }
  }
  private sealed class VborrDouble : Vborr<double> {
    public VborrDobule() {}
    public override double Next() {
      ...
    }
  }
  private sealed class VborrDefault<U> : Vborr<U> {
    public VborrDefault() {}
    public override U Next() {
      ...
    }
  }
  public static Vborr<T> Create<T>() {
    if (typeof(T) == typeof(double) ) { 
      return new VborrDouble();
    } else if ( typeof(T) == typeof(float) ) {
      return new VborrFloat();
    } else {
      return new VborrDefault<T>();
    }
  }
}
JaredPar
Ah, yes, thank you. That is a great idea.
Paul