1

I have a hierarchy of ISomething objects, and now I am trying to get a separate objects to calculate parameters for the ISomething objects. I expect a pretty much one-to-one mapping.

public interface ISomething 
{
    void SetParameters(IParameters p);
}

public interface IParameterCalculator<TSomething> where TSomething : class, ISomething
{
    IParameters Calculate();
}

I would like to make it a bit more type safe, e.g. to make sure that the parameters calculated by a given calculator will fit only to the related something object. So I tried making parameters generic:

public interface IParameterCalculator<TSomething> where TSomething : class, ISomething
{
    IParameters<TSomething> Calculate();
}

I am not sure though how to consume this in the ISomething interface. In C++ there are standard hacks with the templates to achieve this, are there similar techniques in C#? Or any other ideas how to link the IParameterCalculator hierarchy to ISomething in a type-safe way?

Grzenio
  • 35,875
  • 47
  • 158
  • 240
  • 2
    Could you show an example of classes that might implement these interfaces (in a non-generic way) so that we can try to generalize that specific example. As it is, I just can't see what you're actually trying to do with these interfaces. – Servy Feb 05 '14 at 17:47
  • Is Calculate going to set the parameters? I'm confused because I would imagine that you would need to set the parameter before calling the calculate method. What are you really trying to accomplish? Can you provide a real-world example? – Aaron Hawkins Feb 05 '14 at 18:06
  • @Servy The following question has an example http://stackoverflow.com/questions/21599639/how-to-avoid-redundant-code-without-undesirable-double-cast-of-generics. – LCJ Feb 06 '14 at 17:57

2 Answers2

2

One way to do this would be to make the IParameters also dependable on the ISomethings, and you'll also have to declare ISomething as taking a self-type parameter:

public interface ISomething<S> {
  void SetParameters(IParameters<S> p);
}

public interface IParameterCalculator<TSomething> where TSomething : class, ISomething<TSomething> {
  IParameters<TSomething> Calculate();
}

So ISomethings have to be declared passing their own type to the interface:

public class Something : ISomething<Something> {
  ...
}

Note that this does not prevent problems like an ISomething not declaring itself as the type parameter, and you'll also have to change IParameters to be generic. So you should balance the extra type parameters and their semantic constraints (self-type) to the benefit they will bring you.

This is called the curiously recurring template pattern in C++...

Jordão
  • 55,340
  • 13
  • 112
  • 144
1

This is an interesting question.

I believe the following should work:

public interface ISomething<TSomething>
{
    void SetParameters(IParameters<TSomething> p);
}

public interface IParameterCalculator<TSomething>
where TSomething : class, ISomething<TSomething>
{
    IParameters<TSomething> Calculate();
}
Rick Love
  • 12,519
  • 4
  • 28
  • 27