2

these are base type

[DataContract]
public abstract class InputModelBase<T>where T : InputModelParametersBase
{
    [DataMember]
    public string Token { get; set; }
    [DataMember]
    public bool Trace { get; set; }
    [DataMember(Name = "parameters")]
    public T Parameters { get; set; }
}

public class InputModelParametersBase: IInputModelParameters
{
  public string staticToken { get; set; }
  public bool trace { get; set; }
}

public interface IInputModelParameters
{
  public string staticToken { get; set; }
  public bool trace { get; set; }
}

these derived types:

public class SearchInput: InputModelBase<SearchParameters>
{
}

public class SearchParameters: InputModelParametersBase
{
  [DataMember]
  public string Query { get; set; }
}

what i need is create a function that accept all derived types from InputModelBase i tried this but it doesn't work

public void someFunction(InputModelBase<InputModelParametersBase> oInputParams)
{
}

calling someFunction throw exception

var oSearchInput = new SearchInput();
someFunction(oSearchInput);

Severity Code Description Project File Line Suppression State Error CS1503 Argument 1: cannot convert from 'SearchInput' to 'InputModelBase'

how to declare someFunction to make it accept all derived types of InputModelBase?

2
  • You need two generic parameters Function<M,P>(..) where P : InputModelParametersBase where M : InputModelBase<P> Commented Jun 27 at 4:45
  • @FDB please also consider my answer, it might benefit you, although it adds a bit of overhead. Commented Jun 27 at 13:58

2 Answers 2

2

Make your Method as a generic method as following

public void someFunction<T>(InputModelBase<T> oInputParams) where T : InputModelParametersBase
{
}
2
  • 3
    I don't know why I get negative react !! Consider leaving a comment when you add negative vote on any answer will be appreciable
    – Ibram Reda
    Commented Jun 27 at 2:44
  • I've upvoted you but your answers lacks a bit of explanation why it's not possible in the first place. Commented Jun 27 at 14:01
1

There is a bit of confusion assuming that InputModelBase<SearchParameters> inherits from InputModelBase<InputModelParametersBase>, so we can pass SearchInput (which inherits from InputModelBase<SearchParameters>) as a parameter of type InputModelBase<InputModelParametersBase>.

But that's not the case.

InputModelBase<SearchParameters> and InputModelBase<InputModelParametersBase> are different closed generic types that passed their different generic parameters to the open generic type InputModelBase<T>. They don't both inherit from it, but if they did they would be siblings, not parent and child.

If we don't want to use generic methods such as Ibrahim suggested in his answer, we can introduce a covariant interface for our generic open abstract base class:

public interface IInputModelBase<out T> where T : InputModelParametersBase {
    string Token { get; set; }
    bool Trace { get; set; }
    InputModelParametersBase Parameters { get; set; }
}

which we already implement in the abstract class

public abstract class InputModelBase<T> : IInputModelBase<T>
where T : InputModelParametersBase {

This will enable OP's original way of writing the function with the only difference being that we pass a reference of the interface type and not the abstract base class.

public void someFunction(IInputModelBase<InputModelParametersBase> oInputParams) {
}

Possible downside is that we have to keep the interface and the abstract base class in sync.

1
  • Also a very good solution
    – FDB
    Commented Jul 13 at 7:57

Not the answer you're looking for? Browse other questions tagged or ask your own question.