性能命中?匿名类型的列表来实现类似这样的列表(多种类型的多维列表)在 C# 中)

本文关键字:列表 类型 字符串 int 种类 实现 性能 | 更新日期: 2024-12-05 18:37:20

我想知道创建匿名类型的列表是否是有效创建多种类型列表的最佳方式,以及它对一般性能和效率的影响。主要是我只想知道是否有更标准的清单方法?

情况我时不时地发现自己需要创建一个列表,该列表具有多个值,每个值都有不同类型的列表。通常我只会用字典解决这个问题,但在某些情况下,我不关心重复的键值或需要第三个(或很少是第四个)值。通常,这是针对临时列表的,该列表仅跟踪方法中包含的某些内容,例如记录抛出的错误和关联的值,以便在方法结束时我可以将日志文件或其他内容的消息串在一起。

到目前为止,我所拥有的是这样的:

var list = new[] { new { RowNumber = 1, Message = "" } }.ToList();
list.Clear();//clears out the example used to create the anonymous type
list.Add(new { RowNumber = 10, Message = "bla bla" }); //adding to the list

我正在讨论做一些类似扩展之类的事情来简化这件事,但如果性能很糟糕或者有更好的方法,我想知道。

性能命中?匿名类型的列表来实现类似这样的列表<int,字符串,..>(多种类型的多维列表)在 C# 中)

我只是做了一些实验。这是我发现的:

  • 匿名类型与其他任何东西一样好。真的不能说"任何事情",因为我没有尝试所有东西。但我可以告诉你,它们和Tuple<>和混凝土类型一样好。这是合乎逻辑的,因为在幕后,编译器实际上为匿名类型构建类型。本质上,在运行时,它们只是具体的类型。
  • 您的ToList呼叫是多余的。这部分很重要。这与你的直接问题不是很相关,但看看你的例子,你确实new [] { ... }.ToList().这会在创建数组后强制循环。最好使用列表初始化:new List<dynamic> { ... }; .这就是我在示例中使用的内容。

我分别运行了 10,000 次测试:

  • 具有数组初始值设定项的匿名类型(总计 00:00:00.0050338
  • 具有列表初始值设定项的匿名类型(总计 00:00:00.0035599
  • 具有列表初始值设定项的元组(总计 00:00:00.0025857
  • 具有列表初始值设定项的具体类型(总计 00:00:00.0041538)

再次运行它们只会混淆它。唯一一致的结果是,不出所料,数组比直接进入列表慢。

<小时 />

如果要创建扩展方法,则可能需要使用后两个选项之一。匿名类型在它们的范围之外不会很好地传播,我相信你知道。您可以在具体类型和元组之间进行选择。如果您经常使用它和/或在原始方法之外使用它,我会使用具体方法,如果它只需要存在于某个地方,我会使用元组。这真的是我无法为你做出的设计选择。

我更喜欢做一个类。 IL 只是在本机中创建一个匿名类,该类的调用方式与普通类相同,因此没有与之关联的性能影响。 如果你曾经调试过匿名类型,你会注意到这个名字有一个很长的名字,比如 AnonymousTypes.Program+f__1

创建类可提高代码 IMO 的可读性。

public class RowMessage
{
    public int RowNumber { get; set; }
    public string Message { get; set; }
}

你也可以使用元组,但即使这样也不清楚:

    public void MyMethod()
    {
        Tuple<int, string> myTuple = new Tuple<int, string>(1, "hi");
        List<Tuple<int, string>> myTupList = new List<Tuple<int, string>>();
        myTupList.Add(myTuple);
    }

由于您正在谈论丰富异常信息,因此值得一提的是,Exceptionclass 实现了一个名为 Data 的属性,该属性的类型为 IDictionary,可用于附加其他信息。

    try
    {
        throw new FileNotFoundException{ Data ={ { "TEST", "Hello World" } } };
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Data["TEST"]);
        ...
        e.Data.Add("Whatever", DateTime.Now);
    }

如果您发现自己多次添加相同的信息,请考虑一些将某些信息添加到给定异常的帮助程序方法。这也可以照顾到重复的键,这些键使用某种数字后缀,如fileName_1等递增,你明白了。您还可以创建一种标准化方法来输出您自己提供的那些信息。


如果你想要一个更复杂的方法,你可以简单地使用List,但让这个列表的使用者处理每种类型。这基本上是DebuggerTypeProxy-Atrribute背后的想法

因此,例如,您可以使用这样的模式:

foreach(var typeGroup in additionalInformation.GroupBy(item => item.GetType())
{
    ITypedLogHandler handler = GetHandlerFor(typeGroup.Key);
    handler.WriteLog(typeGroup);
}

一般来说,我能想到的整个想法的唯一原因是一些方便的调试/登录方法。其他任何东西都应该真正使用强类型。