简体   繁体   中英

How to use Generics method using Interface in c#? Getting Error

I have interface with two methods,

I am trying to create the generic interface INewReleaseValidationRule where T : INewReleaseValidationEntity that will have Run() method.

Then I have another class ValidationClass, which is inheriting NewReleaseValidationEntityBase class. I am trying to call the Run() method in ValidateInputMethod() that is in SomeOtherClass. But I am getting error,

**Cannot convert from System.Collections.Generic.List to System.Collections.Generic.IList ** SalesForecastViewModel is indirectly derived class of INewReleaseValidationEntity, so as per runtime polymorphism it should work?

public interface INewReleaseValidationRule<T> where T : INewReleaseValidationEntity
{
    void Run(CtxNewRelease ctx, IList<T> entities);
    string GetMessage(string messageName, string fallbackMessage);
}

public interface INewReleaseValidationEntity
{
    string GetDefaultSkipMsg();
    List<ValidationError> ValidationErrors {get;set;}
    bool Valid { get; set; }
    void SetValidation(string errorCode, string errorMessage, string errorField, Severities severity);
    }

public abstract class NewReleaseValidationEntityBase : INewReleaseValidationEntity
{

    public NewReleaseValidationEntityBase()
    {
        Valid = true;
    }
 //Implementation all the methods of INewReleaseValidationEntity 
}


public class ValidationClass : NewReleaseValidationEntityBase
{
    public ValidationClass()
    {
        MessageHelper.LoadToCache(TYPECODE);
    }

    public string GetMessage(string messageName, string fallbackMessage)
    {
        return MessageHelper.TryGetFromCache(messageName, fallbackMessage);
    }

    public void Run(Context.CtxNewRelease context, IList<INewReleaseValidationEntity> sList)
    {
       //Some code statement to perform validation
    }
}

Then I have view model class that is inheriting,

public class SalesForecastViewModel : NewReleaseValidationEntityBase
{
   //Some properties and functions
}

Then in another class, I am trying to call the generic method Run(),

Public Class SomeOtherClass {
     public void ValidateInput(List<SalesForecastViewModel> viewModel)
    {

            ValidationClass vcObject = new ValidationClass();
            **vcObject.Run(context, viewModel);**  //Here viewModel is of child class. It should convert it runtime.

        }
    }

}

//Sorry for long confusing code.

The issue you're facing is caused by the fact, that the IList<T> interface is not covariant. What that really means, is that an IList<ParentType> cannot be assigned to an instance of IList<ChildType> . The documentation will help you understand the topic more.

So there are two paths you can take here:

  1. Use arrays to benefit from implicit reference conversion. Here what the code will look like then:

    vsObject.Run(context, viewModel.ToArray());

  2. Switch to a covariant interface, which IEnumerable<T> is, in your code. So this will require you to change the signature of the ValidationClass.Run method as follows:

    void Run(CtxNewRelease ctx, IEnumerable<T> entities)

This will make the passed in List<SalesForecastViewModel> assignable to a variable of type IEnumerable<INewReleaseValidationEntity> .

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM