【问题标题】:How to generalize using C# generics? [duplicate]如何使用 C# 泛型进行泛化? [复制]
【发布时间】:2018-03-15 15:17:40
【问题描述】:

我正在尝试制作一个可以将各种文件格式解析为实体类型对象以存储在数据库中的结构。

我想让代码尽可能易于阅读,并使用其他文件格式和实体类型相互独立地扩展。

一般来说,我有一个文件解析器,它使用一个文件并返回一个 DTO 模型。然后这个 DTO 模型被一个转换器使用,它返回一个数据库实体对象。解析器、转换器和 DTO 模型都扩展了抽象类以避免代码重复。该过程由一个名为 Service 的类执行。

下面是代码的精髓:

class Service
{
    public void Run()
    {
        var model = new DerivedModel<DerivedRow>();
        var parser = new DerivedParser<DerivedModel<DerivedRow>>(model);
    }
}

class DerivedModel<TRow> : AbstractModel<DerivedRow>
    where TRow : DerivedRow
{
    public override DerivedRow NewRow()
    {
        return new DerivedRow();
    }
}

abstract class AbstractModel<TRow>
{
    public abstract TRow NewRow();
}

class DerivedRow : AbstractRow
{
}

abstract class AbstractRow
{
}

class DerivedParser<TModel> : AbstractParser<TModel>
    where TModel : AbstractModel<AbstractRow>
{
    public DerivedParser(TModel model)
    {
        Model = model;
    }

    public override TModel Parse()
    {
        var row = Model.NewRow();
        return Model;
    }
}

abstract class AbstractParser<TModel>
{
    public TModel Model { get; protected set; }

    public abstract TModel Parse();
}

类型检查器抱怨服务类中的这行代码:

var parser = new DerivedParser>(model);

错误是:

错误 CS0311 类型“Sandbox.GenericTest.DerivedModel”不能用作泛型类型或方法“DerivedParser”中的类型参数“TModel”。没有从“Sandbox.GenericTest.DerivedModel”到“Sandbox.GenericTest.AbstractModel”的隐式引用转换。

我尝试过将一些接口与抽象类结合使用,但这只会使事情变得复杂。

有什么建议吗?我正在尝试以这种方式在 C# 中做的事情吗?

【问题讨论】:

  • 虽然副本没有回答如何做你想做的事,但它回答了为什么你不能
  • 我相信您可以通过为 DerivedParser 提供 2 个泛型类型、一种用于模型的泛型类型和一种用于行的泛型类型来解决它。虽然我不确定。
  • @CamiloTerevinto 看起来它实际上是可能的(见答案),但感谢 Covarianca/Contravariance 参考! :)
  • @bramve 你说对了一部分! :) 看看答案。

标签: c# generics nested-generics


【解决方案1】:

尝试通过 TModel 并且错误消失。 您需要向 AbstractParser 提及模型的类型。一旦你通过了那个错误就会消失。 这是代码

class Service
{
    public void Run()
    {
        var model = new DerivedModel<DerivedRow>();
        var parser = new DerivedParser<DerivedModel<DerivedRow>, DerivedRow>(model);
    }
}

class DerivedModel<TRow> : AbstractModel<DerivedRow>
    where TRow : DerivedRow
{
    public override DerivedRow NewRow()
    {
        return new DerivedRow();
    }
}

abstract class AbstractModel<TRow> where TRow : AbstractRow
{
    public abstract TRow NewRow();
}

class DerivedRow : AbstractRow
{
}

abstract class AbstractRow
{
}



class DerivedParser<TModel, TRow> : AbstractParser<TModel, TRow>
        where TModel : AbstractModel<TRow> where TRow : AbstractRow
{
    public DerivedParser(TModel model)
    {
        Model = model;
    }

    public override TModel Parse()
    {
        var row = Model.NewRow();
        return Model;
    }
}

abstract class AbstractParser<TModel, TRow> where TRow : AbstractRow
{
    public TModel Model { get; protected set; }

    public abstract TModel Parse();
}

【讨论】:

    猜你喜欢
    • 2013-12-19
    • 2019-07-25
    • 2011-05-07
    • 1970-01-01
    • 1970-01-01
    • 2013-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多