【问题标题】:Casting an IEnumerable<T> to wrapper class将 IEnumerable<T> 强制转换为包装类
【发布时间】:2018-01-08 17:28:10
【问题描述】:

我有一个实际上是 IEnumerable 包装器的类:

public class MyThings : IEnumerable<Thing>
{

}

我像这样创建Thing 的枚举:

var things = new [] {new Thing (), new Thing()};

据此,我想创建一个MyThings 的实例——类似于:

var myThings = things as MyThings;

这当然行不通。

一种解决方案是将Add 方法添加到MyThings 和内部List&lt;Thing&gt;

public class MyThings : IEnumerable<Thing>
{
    private readonly List<Thing> list = new List<Thing>();

    public MyThings this[int index]
    {
        get { return list[index]; }
        set { list.Insert(index, value); }
    }

    public IEnumerator<Thing> GetEnumerator()
    {
        return list.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void Add(Thing thing)
    {
        list.Add(thing);
    }
}

这样,我可以通过自动初始化来创建它,例如:

var things = new MyThings {new Thing (), new Thing()};

但这似乎不是很优雅。

有没有办法铸造?

编辑: 本着“你为什么要这样做”的精神

这样我们就可以将自定义 JsonConverter 应用于整个类型 (MyThings)

【问题讨论】:

  • 呃,没有 cmets 的投票者在这个网站上的情况最糟糕。
  • 我之前没有在 .NET 中使用过 Json,但我认为大多数 Json 序列化框架都会支持开箱即用的集合。只要有Thing的转换器,你就不能简单地序列化Thing[]IEnumerable&lt;Thing&gt;IList&lt;Thing&gt;吗?
  • 这是因为您想在一个地方以一种方式序列化 JSON,但在另一个地方以不同的方式序列化 JSON,而底层类型仍然相同?
  • 是的,这有点难以解释(并且超出了这个问题的范围) - 但基本上我们的Thing collection 以特定方式存储在 json 中(第三方要求) - 我们的类具有这种类型的属性,都需要以相同的方式序列化,而不是用 JsonConverter 装饰每个属性,我们考虑拥有这个包装类 - 这几乎工作得很好跨度>
  • @Alex Gotcha。将包装类埋在 Internal 命名空间中可能是个好主意,以阻止人们在您描述的有限范围之外使用它。

标签: c# generics collections casting


【解决方案1】:

一个数组,来自:

var things = new [] {new Thing (), new Thing()};

是一个数组 (Thing[])。它永远是一个数组,除了一个数组之外别无他物。它不会是MyThings

现在,您可以添加一个 转换运算符,它允许在它们之间进行显式或隐式强制转换,但是 很可能您所做的只是添加不必要的中间数组分配.坦率地说,我认为你的 Add 加上集合初始化器语法是你最好的选择。

但是是的,您也可以添加:

public static implicit operator MyThings(Thing[] things) {
    // your logic here
}

然后就可以了:

var arr = new[] { new Thing(), new Thing() };
MyThings things = arr;

或者如果你使用explicit而不是implicit,那么:

var arr = new[] { new Thing(), new Thing() };
MyThings things = (MyThings)arr;

如果MyThings 只是 包装了数组,那么运算符方法可能是一个好主意,并且您将其存储在一个字段中而不复制它,即如果您的实现基本上是:

this._things = things;

【讨论】:

  • 我不喜欢这种简单的转换,因为目前尚不清楚生成的包装器是否实际上是一个包装器。它是包装 original 数组,还是创建一个副本?除非您深入研究MyThings 的来源,否则不清楚。我也质疑 MyThings 可变的价值,但那是 OP 的设计决定,而不是你的。
猜你喜欢
  • 1970-01-01
  • 2020-05-07
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多