3

I've been reading the documentation here and I couldn't get where I can achieve what I need - sort of an overload for constraints on type parameters. I "technically" don't know how to call it thus I mentioned "overload". Here's an example of what I'm trying to achieve:

class Test<T> {
  private Test(string x) {
  }  

  public static Test<T> OpTest(T t) {
    return new Test<T>("test string") {
      Value = t,
    }
  }

  public T Value1 {get;set;}
  public string X {get;set;}
}

// Sample usage
var result = Test<SomeClass>.OpTest(instanceOfSomeClass);

And here's what I wanted have...

//... that I can do this
var result = Test<SomeClass>.OpTest(instanceOfSomeClass);
//and also sometimes this
var anotherResult = Test<SomeClass, SomeOtherClass>
    .OpTest(instanceOfSomeClass, instanceOfSomeOtherClass);

I am able to achieve this by creating another class with a different constraint like this:

class Test<T, U> : Test<T> {
  private Test(string x):base(x) { }
  public static Test<T, U> OpTest(T t, U u) {
    return new Test<T, U>("test string") {
      Value1 = T,
      Value2 = U,
    }
  }

  public U Value2 {get;set;}
}

Although that works the way I wanted it to, I feel like something is wrong. Is it? Or is there a better way of doing it? Additionally, I only not feel it's wrong but I now have to duplicate (copy+paste) some logic between Test<T> and Test<T,U>.

von v.
  • 16,868
  • 4
  • 60
  • 84
  • 3
    Considering how many `Func` overloads there are, there is nothing wrong with creating overloaded classes for each expected number of types. There isn't anything like optional type parameters as of C# 6 though. – Ron Beyer Aug 20 '15 at 17:46
  • It sounds like you might be looking for variadic type parameter support, which is not currently possible in C#. DRYing up the code like in rbaghbanli's answer is about the best that you can hope for right now. See: http://stackoverflow.com/questions/15417174/using-the-params-keyword-for-generic-parameters-in-c-sharp/30248304#30248304 and http://stackoverflow.com/questions/4046397/generic-variadic-parameters/4046525#4046525 for more information. – Tyree Jackson Aug 20 '15 at 18:28
  • Thanks for the link @TyreeJackson. The first one make sense. I guess I'll stick to what I have "for now" until a clever approach is revealed (if there's even any). And yes inheritance is in place already, that's not what I'm up to really. – von v. Aug 20 '15 at 18:36

1 Answers1

1

DRY way to write it:

class Test<T> {
  private Test(string x) {
  }  

  public static Test<T> OpTest(T t) {
    return new Test<T>("test string") {
      Value1 = t,
    }
  }

  public T Value1 {get;set;}
  public string X {get;set;}
}

class TestExtra<T, U> : Test<T> {
  private TestExtra(string x) : base(x) {
  }  

  public static TestExtra<T, U> OpTestExtra(T t, U u) {
    return new Test<T>("test string") {
      Value1 = t,
      Value2 = u
    }
  }

  public U Value2 {get;set;}
}


var result = Test<SomeClass>.OpTest(instanceOfSomeClass);
var anotherResult = TestExtra<SomeClass, SomeOtherClass>
    .OpTestExtra(instanceOfSomeClass, instanceOfSomeOtherClass);
Riad Baghbanli
  • 3,105
  • 1
  • 12
  • 20
  • Thanks for the tip rbaghbanli but I'm aware of that already ;) What I'm really after is those method signatures that I have to create in each of the new "overloaded classes" and codes in between. For now, I'll take what @Ron Beyer mentioned that is fine to create overloaded classes. Any other ideas are welcome. – von v. Aug 20 '15 at 18:27
  • If you are concerned with TestOp code repeating variable setup, it can be DRYed up further. If instead of factory method, you will use either constructor or setter method, then use of base(x, y, ...) for the constructor or base.set(x, y, ...) for setter method you get even less code repetition. – Riad Baghbanli Aug 20 '15 at 20:17