【问题标题】:Compare type of IEnumerable<T>比较 IEnumerable<T> 的类型
【发布时间】:2010-09-14 12:40:28
【问题描述】:

我有一个字典,它根据传入的值返回一个方法。定义如下:

Dictionary<Type, IXmlWriterConverter>

我现在添加了一个新函数,它的 Key/type 设置为 IEnumerable,到目前为止一切都很好。 但是当我使用包含两个 DataTables 的 List 执行单元测试但字典找不到键时,例如我的类型转换不同。

为什么会这样?解决我的问题的正确尝试是什么?

编辑:抱歉,这里是请求的代码;-)

生成测试值的函数:

public IEnumerable<DataTable> CreateTestDataTableList()
{
    var resultDataTable = new List<DataTable>();

    resultDataTable.Add(CreateTestTable("testTable1", 2));
    resultDataTable.Add(CreateTestTable("testTable2", 3));

    return resultDataTable;
}

单元测试调用的函数:

public void Write(XmlWriter xmlWriter, object value)
{
    ...
    converter = FindConverter(value.GetType());
}

查字典功能:

public IXmlWriterConverter FindConverter(Type type)
{
    if(Converters.ContainsKey(type))
    {
        return Converters[type];
    }
    return null;
}

2.编辑:

将值添加到字典的代码:

public void Add(IXmlWriterConverter xmlWriterConverter)
{
    if(Converters.ContainsKey(xmlWriterConverter.InputType))
    {
        Remove(xmlWriterConverter);
    }

    Converters.Add(xmlWriterConverter.InputType, xmlWriterConverter);
}

InputType 是转换器的只读(获取)属性。我检查了添加到字典中的类型并注册为 IEnumerable,但是当我在传入列表时检查 typeof 时,类型是 List 而不是 IEnumerable。有人告诉我这是因为我将值作为对象传递。

【问题讨论】:

  • 或许你应该把相关代码贴出来,这样其他人才能真正看到发生了什么......
  • 你能提供一些示例代码吗?
  • @dkson 也许我应该一开始就这样做.. 抱歉懒惰 ;-)
  • Dictionary添加项目的代码在哪里?
  • 谢谢。我现在发布了我的答案。

标签: c# generics types ienumerable


【解决方案1】:

这对我来说确实是一个代码很臭的解决方案,它降低了效率,但你也可以在 Type 上迭代 GetInterfaces() 方法,如下所示:

List<DataTable> l = new List<DataTable>();
var t = l.GetType();
var ints = t.GetInterfaces();

然后您可以查找类型,如果不起作用,请查找它的接口。

然而,这感觉就像一个可怕的 hack,这通常表明需要做更多的设计工作。是不是不能把 List 类型放到字典里?有没有更好的方法来进行这种查找?

另外,关于进行字典查找的说明:使用 TryGetValue 方法效率更高,如下所示:

public IXmlWriterConverter FindConverter(Type type)
{
    IXmlWriterConverter converter;
    if( Converters.TryGetValue(type, out converter) )
    {
        return converter;
    }

    return null;
}

当你这样做时,它只对字典进行一次查找,而如果你使用 ContainsKey,它必须进行两次查找。

【讨论】:

  • 嗨 Rob,是的,我最初也想使用 List,但在与工作中的高级开发人员交谈后,我们想出了一个不同的解决方案,允许我们使用 IEnumerable。不过还是谢谢你的小费。
【解决方案2】:

这有点骇人听闻,但在查看您的代码时,我唯一想到的就是添加其他通用写入方法:

public void Write<TValue>(XmlWriter writer, TValue value) {
// ...
}

这允许为 IEnumerable 识别正确的类型,并使其他 Write 方法不会破坏任何现有代码。

【讨论】:

    【解决方案3】:

    可能您正在尝试检索 List 类型而不是 IEnumerable(继承在这种情况下不起作用)

    如果您想要更多详细信息和更确定的答案,请粘贴进行查找的代码:)

    【讨论】:

      【解决方案4】:

      您还应该发布您在哪里检索测试值的代码。但是根据您提供的内容,您是否可能使用非通用 IEnumerable 来检索值,而不是您用来生成它们的通用版本?

      【讨论】:

      • 不,我从不使用非通用版本的 IEnumerable。并且测试失败,因为选择了通用转换器。所以我无法为您提供测试的返回值。
      【解决方案5】:

      InputType 是只读的 (get) 转换器的属性。我检查了 添加到字典中的类型和 注册为 IEnumerable, 但是当我检查 typeof 当传入我的列表时,类型是 列出而不是 IEnumerable。有人告诉我 发生这种情况是因为我通过了 值作为对象。

      就像他们在MythBusters 上所说的那样,好吧,这就是你的问题! 即使List 是-a IEnumerable 代表每个对象的Type 对象绝对不一样。在程序员行话中,typeof(List) != typeof(IEnumerable)。这就是查找不起作用的原因。

      【讨论】:

      • 确实如此,我也注意到了,但为什么它会将我最初传入的 IEnumerable 引用到 List?我想这就是我想问的..
      • @Mark:我不确定。我想我必须看到更多的代码来回答这个问题。具体来说,我需要查看传递给Writevalue 是如何获得的,以及InputType 是如何获得的。
      • 唯一缺少的代码 sn-p 是来自单元测试的调用。但这会将生成的 IEnumerable 作为 write 函数所需的对象传入。据我所知,该对象被强制转换为 List 而不是 IEnumerable。通过实现我的写入版本的通用版本,我能够解决问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      相关资源
      最近更新 更多