C#泛型和重写方法

时间:2019-10-28 19:12:10

标签: c# generics interface overriding

我创建了question,并意识到这是由于我的某些设计错误所致。但是,我确实认为该概念可能有用,并且我想知道如果可能的话,如何解决类似的问题。

我想创建一个将两个数字相加的算法,无论是string还是int。我还希望能够在控制台中输出所有内容,并希望避免代码重复。我创建了一个generic interface,它会根据模型而变化。然后是一个处理两个成员加法的类。请注意,数据来自处理程序类(在现实生活中,它们从外部数据获取信息以填充模型)。

请注意,我确实知道有很多更简单的掺杂方法,但是我想了解为什么它不起作用。现在,该代码无法在{{ 1}}归因于ValidateHandler<T>(IAddHandler<T> handler)。为什么不能选择正确的覆盖方法?我尝试将泛型添加到重写的方法中,但仍然无法正常工作。如何使cannot convert from 'T' to 'Test.Models.StringModel'从类型中选择正确的方法?

这是我写的代码。

型号:

ValidateHandler<T>

接口:

public class IntegerModel
{
    public int A { get; set; }

    public int B { get; set; }

    public int C { get; set; }
}

public class StringModel
{
    public string A { get; set; }

    public string B { get; set; }

    public string C { get; set; }
}

处理程序:

public interface IAddHandler<T>
{
    T Add();

    void GetData();
}

这里是主要功能

public class IntegerHandler : IAddHandler<IntegerModel>
{
    public IntegerModel IntegerModel { get; set; }

    public void GetData()
    {
        // Get Info to Add from external file for example
        IntegerModel = new IntegerModel { A = 10, B = 20 };
    }

    public IntegerModel Add()
    {
        IntegerModel.C = IntegerModel.A + IntegerModel.B;

        return IntegerModel;
    }
 }

public class StringHandler : IAddHandler<StringModel>
{
    public StringModel StringModel { get; set; }

    public void GetData()
    {
        // Get Info to Add from external file for example
        StringModel = new StringModel { A = "10", B = "20" };
    }

    public StringModel Add()
    {
        StringModel.C = StringModel.A + StringModel.B;
        return StringModel;
    }
 }

我知道我可以执行以下操作,但是这样做似乎无效,因此我看不到使用泛型的意义。

public static void Main(string[] args)
{
    var integerHandler = new IntegerHandler();
    var stringHandler = new StringHandler();

    ValidateHandler(integerHandler);
    ValidateHandler(stringHandler);
}

public static void ValidateHandler<T>(IAddHandler<T> handler)
{
    handler.GetData();
    var result = handler.Add();

    WriteResults(result);
}

public static void WriteResults(StringModel model)
{
    Console.WriteLine(model.C);
}

public static void WriteResults(IntegerModel model)
{
    Console.WriteLine(model.C);
}

1 个答案:

答案 0 :(得分:2)

这就是我的建议。这种方法对泛型的投入较小。我相信,比起完全通用的解决方案,要更容易动手。

public interface IResult
{
    Object Result { get; }
}

public interface IModel : IResult
{
    Object A { get; }
    Object B { get; }
}

public class Model<T> : IModel
{
    public T A { get; set; }
    public T B { get; set; }
    public T Result { get; set; }

    //  The "IModel.*" prefix means this is an "explicit" implementation of the IModel 
    //  interface. That means that ordinarily, model.A gets you the above strongly typed
    //  A property, but with an explicit cast to IModel, you get the non-generic IModel 
    //  version: model.A is int or whatever T is; ((IModel)model).A is object. 
    //
    //  These getters don't recurse because this is of type Model<T>, not IModel.
    //  If T is List<String>, a subclass could override this to return 
    //  String.Join(", ", Result);
    Object IModel.A => A;
    Object IModel.B => B;
    Object IResult.Result => Result;
}

public interface IAddHandler<T> where T : IModel
{
    T Model { get; set; }
    T Add();

    void GetData();
}

public class IntegerHandler : IAddHandler<Model<int>>
{
    public Model<int> Model { get; set; }

    public void GetData()
    {
        // Get Info to Add from external file for example
        Model = new Model<int> { A = 10, B = 20 };
    }

    public Model<int> Add()
    {
        Model.Result = Model.A + Model.B;

        return Model;
    }
}

public class StringHandler : IAddHandler<Model<string>>
{
    public Model<string> Model { get; set; }

    public void GetData()
    {
        // Get Info to Add from external file for example
        Model = new Model<string> { A = "10", B = "20" };
    }

    public Model<string> Add()
    {
        Model.Result = Model.A + Model.B;

        return Model;
    }
}

主要:

class Program
{
    public static void Main(string[] args)
    {
        var integerHandler = new IntegerHandler();
        var stringHandler = new StringHandler();

        ValidateHandler(integerHandler);
        ValidateHandler(stringHandler);
    }

    //  This method must require T to be IModel because IAddHandler<T> requires 
    //  T to be IModel.
    public static void ValidateHandler<T>(IAddHandler<T> handler) where T : IModel
    {
        handler.GetData();
        var result = handler.Add();

        //  IModel inherits from IResult. Hence, anything that implements IModel 
        //  must implement IResult. So this is an implicit cast, even though IResult 
        //  is implemented explicitly. 
        WriteResults(result);
    }

    //  The parameter here could be IModel instead, but maybe there are other non-model 
    //  classes that implement IResult.
    public static void WriteResults(IResult result)
    {
        Console.WriteLine(result.Result);
    }
}