Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如果我需要存储几个不相关的类型,但需要按需提供特定类型,我应该如何处理这种情况?_.net_Generics - Fatal编程技术网

.net 如果我需要存储几个不相关的类型,但需要按需提供特定类型,我应该如何处理这种情况?

.net 如果我需要存储几个不相关的类型,但需要按需提供特定类型,我应该如何处理这种情况?,.net,generics,.net,Generics,我正在为我们使用的一个重要的内部测试工具使用的文件编写一个编辑器。这个工具本身是大型的、复杂的,重构或重写将占用比我们在可预见的未来所能投入的资源更多的资源,因此,当涉及到大型修改时,我的手被束缚住了。我必须使用.NET语言 这些文件是该工具使用的四个类的XML序列化版本(让我们称它们为A、B、C和D)。当一切正常时,这些类形成一个树结构。我们的编辑器的工作方式是加载一组文件,对它们进行反序列化,找出它们之间的关系,并跟踪它能找到的任何不良状态。我们的想法是不再手工编辑这些文件,这会导致大量错误

我正在为我们使用的一个重要的内部测试工具使用的文件编写一个编辑器。这个工具本身是大型的、复杂的,重构或重写将占用比我们在可预见的未来所能投入的资源更多的资源,因此,当涉及到大型修改时,我的手被束缚住了。我必须使用.NET语言

这些文件是该工具使用的四个类的XML序列化版本(让我们称它们为A、B、C和D)。当一切正常时,这些类形成一个树结构。我们的编辑器的工作方式是加载一组文件,对它们进行反序列化,找出它们之间的关系,并跟踪它能找到的任何不良状态。我们的想法是不再手工编辑这些文件,这会导致大量错误

对于一种特殊类型的错误,我希望维护一个包含所有有问题的文件的集合。这四个类都会有问题,我希望尽可能减少代码的重复。一个重要的要求是,用户需要能够获得成套物品;例如,与
GetAs()
方法相比,他们需要获取所有有错误的对象,并告诉它们迭代整个集合并找出它们想要的对象是不可接受的。因此,我的第一个想法是创建一个与反序列化对象和一些元数据相关的通用项来指示错误:

public class ErrorItem<T>
{
    public T Item { get; set; }
    public Metadata Metadata { get; set; }
}
但是,这会对公共接口产生影响。我真正想要的是返回适当的
ErrorItem
泛型类型,如下所示:

public ErrorItem<A>[] GetA()
public ErrorItem[]GetA()
这是不可能的,因为我只能存储
ErrorItem
!我在脑子里考虑过一些变通办法;大多数情况下,它们包括在运行中创建一个新的
ErrorItem
,它的类型是适当的,但感觉有点难看。另一个想法是使用
字典
按类型组织项目,但它似乎仍然不正确


有什么模式可以帮我吗?我知道解决这个问题的最简单方法是添加一个a、B、C和D派生自的基类,但我正试图对原始工具产生尽可能小的影响。任何变通方法的成本是否足够大,以至于我应该推动更改初始工具?

如果A、B、C和D没有任何共同点,那么添加基类实际上不会带来任何好处。它只是一个空类,实际上与object相同


我只需要创建一个没有泛型的ErrorItem类,将Item设置为对象,并在需要使用引用的对象时进行一些转换。如果要使用A、B、C或D类的任何属性或方法,而不是Guid,则必须强制转换它们。

这就是您要查找的吗

private List<ErrorItem<object>> _allObjects = new List<ErrorItem<object>>();

public IEnumerable<ErrorItem<A>> ItemsOfA
{
    get
    {
        foreach (ErrorItem<object> obj in _allObjects)
        {
            if (obj.Item is A)
                yield return new ErrorItem<A>((A)obj.Item, obj.MetaData);
        }
    }
}

到目前为止,我的答案是fryguybob和Mendelt Siebenga的答案的组合

正如Mendelt Siebenga指出的那样,添加基类只会污染名称空间并引入类似的问题。我可以更好地控制哪些项目可以进入集合,但我仍然需要存储
ErrorItem
,并仍然进行一些转换,因此我会有一个稍微不同的问题,其根本原因是相同的。这就是我选择这篇文章作为答案的原因:它指出,无论发生什么,我都必须进行一些类型转换,而KISS将说明额外的基类和泛型太多了


我喜欢fryguybob的回答,不是因为解决方案本身,而是因为它提醒我关于
收益率返回的问题,这将使非缓存版本更易于编写(我打算使用LINQ)。我认为缓存版本更明智一点,尽管预期的性能参数不会使非缓存版本明显变慢。

感谢您的回复。大多数人只会发火,忘记问题。很高兴看到你通过回顾答案和分享你的结论来增加一些价值。
private List<ErrorItem<object>> _allObjects = new List<ErrorItem<object>>();

public IEnumerable<ErrorItem<A>> ItemsOfA
{
    get
    {
        foreach (ErrorItem<object> obj in _allObjects)
        {
            if (obj.Item is A)
                yield return new ErrorItem<A>((A)obj.Item, obj.MetaData);
        }
    }
}
private List<ErrorItem<A>> _itemsOfA = null;

public IEnumerable<ErrorItem<A>> ItemsOfACached
{
    if (_itemsOfA == null)
        _itemsOfA = new List<ErrorItem<A>>(ItemsOfA);
    return _itemsOfA;
}