【问题标题】:Can I somehow tidy up this (overuse?) of generics?我可以以某种方式整理这个(过度使用?)泛型吗?
【发布时间】:2012-11-27 18:48:04
【问题描述】:

我正在构建一个看起来像这样的通用平面文件阅读器。

 public class GenericReader<TComposite, THeader, TData, TTrailer> 
    where TComposite : GenericComposite<THeader, TData, TTrailer>, new()
    where THeader : new()
    where TData : new()
    where TTrailer : new()
{
    public TComposite Read()
    {
        var composite = new TComposite();

        composite.Header = new THeader();
        composite.Data = new TData();
        composite.Trailer = new TTrailer();

        return composite;
    }        
}

可以这样吃。

var reader = new GenericReader<Composite<Header, Data, Trailer>, Header, Data, Trailer> ();

var composite = reader.Read();
Console.WriteLine(composite.Data.SomeProperty);

Console.ReadLine();

这里是使用的类。

public class Composite<THeader, TData, TTrailer> : GenericComposite<THeader, TData, TTrailer>
{

}

public class GenericComposite<THeader, TData, TTrailer>
{
    public THeader Header { get; set; }

    public TData Data { get; set; }

    public TTrailer Trailer { get; set; }
}

public class Header {
    public string SomeProperty { get { return "SomeProperty"; } } 
}

public class Data {
    public string SomeProperty { get { return "SomeProperty"; } } 
}

public class Trailer {
    public string SomeProperty { get { return "SomeProperty"; } } 
}

有没有办法可以删除或封装 GenericReader 中的泛型类型信息?我正在寻找一双额外的眼睛来向我展示我一直缺少的东西。我们已经在返回接口方面做了一些事情,并让消费者进行强制转换,但在我看来,这只是将责任转移到了错误的位置,另外还有一点性能损失。

谢谢。

编辑:我不需要 TComposite,我可以返回 GenericComposite。我怎么能错过呢?

public class GenericReader<THeader, TData, TTrailer> 
    where THeader : new()
    where TData : new()
    where TTrailer : new()
{
    public GenericComposite<THeader, TData, TTrailer> Read()
    {
        var composite = new GenericComposite<THeader, TData, TTrailer>();

        composite.Header = new THeader();
        composite.Data = new TData();
        composite.Trailer = new TTrailer();

        return composite;
    }        
}

public class GenericComposite<THeader, TData, TTrailer>
{
    public THeader Header { get; set; }

    public TData Data { get; set; }

    public TTrailer Trailer { get; set; }
}

【问题讨论】:

  • 您可能想查看code review SE。它真的更适合这样的审查任务。
  • 我认为这个问题很合适;它不是一个代码审查,而是一个关于泛型类型参数相互依赖的问题(并且类型系统讨论绝对是 SO 中的主题)以及简化它的方法..
  • 对我来说,您的 GenericReader 听起来更像是一个工厂而不是泛型类型,除非我遗漏了什么。听起来你会创建它只是为了在之后处理它。那么除了提供 Composite 之外,还有 GenericReader 存在的理由吗?复合体不能有一些静态方法来生成自身的实例吗?
  • 抱歉不同意,但我喜欢至少在 Read() 等方法中使用接口,因为它确保 Read 方法在处理各种用例时不会膨胀到地狱/边缘情况。也就是说,我也同意你的观点,这是泛型地狱。我想我会尝试在没有任何泛型的情况下实现一些实例,以更好地了解边缘在哪里,泛型在哪里增加价值,以及在不牺牲灵活性的情况下可以用特定实现替换它们。
  • @lightstriker 在实际实现中还有很多工作要做。

标签: c# design-patterns generics types


【解决方案1】:

没有办法消除对您拥有的通用约束的类型声明的需要。

但是,您的用例表明这是最常见的行为:

var reader = new GenericReader<Composite<Header, Data, Trailer>, 
    Header, Data, Trailer>();

如果是这种情况,您可以对某些模式的使用频率做出假设,您可以从具有封闭类型定义的泛型类继承一个类型(或一组类型),这样可以更轻松地使用。

在上述情况下,您可以为基本、最常见的情况(除了通用定义)提供这些类:

public class Composite : GenericComposite<Header, Data, Trailer> { }

public class GenericReader : GenericReader<
    Composite, Header, Data, Trailer>
{ }

然后会像这样使用:

var reader = new GenericReader();

var composite = reader.Read();

Console.WriteLine(composite.Data.SomeProperty);

Console.ReadLine();

对于高度专业化的情况,您仍然可以使用具有通用参数的类型,但对于常见用例(您通过分析/领域知识确定),您可以确定最常见的类型并提供类设置类型参数来协助。

【讨论】:

  • 这就是我现在正在做的事情。应该将其添加到问题中。比较理智的解决方案imo!
  • @JefClaes 我最近遇到了一个情况,我有三个泛型参数,两个是常规用例,我发现为继承的参数提供预定义的类型参数(我推荐的)是最适合我。也许是偶然的。
猜你喜欢
  • 1970-01-01
  • 2021-07-18
  • 1970-01-01
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-05
  • 1970-01-01
相关资源
最近更新 更多