简体   繁体   English

性能受到打击吗? 匿名类型的列表以实现类似此列表的功能 <int, string, …> (C#中的多种类型的多维列表)

[英]Performance Hit? list of anonymous type to achieve something like this List<int, string, …> (a multi-dimensional list of multiple types) in c#)

I am wondering about whether or not creating a list of an anonymous type is the best way to effectively create a list of multiple types as well as its effect on general performance and efficiency. 我想知道是否创建匿名类型的列表是否是有效创建多个类型的列表及其对总体性能和效率的影响的最佳方法。 Mainly I just want to know if there is a more standard way of doing List? 主要是我只想知道是否有更标准的List方法?

Situation I every now and then find myself with a need to create a list that has multiple values each of a different type, List. 情况我时不时地发现自己需要创建一个包含多个值的列表,每个值都有不同的类型,即List。 Normally i would just resolve this with a Dictionary, but then there are the cases where i don't care about duplicated key values or need a 3rd (or rarely 4th) value. 通常,我只是用Dictionary解决这个问题,但是在某些情况下,我不在乎重复的键值或需要第3个(或很少有第4个)值。 Usually this is for temporary list that just track something contained in a method like logging thrown errors and an associated value so that at the end of the method i can string together the messages for a log file or something. 通常,这是用于临时列表的,它仅跟踪方法中包含的某些内容,例如记录引发的错误和相关值,以便在方法结束时,我可以将消息的字符串一起整理成日志文件或其他内容。

What i have so far is this: 我到目前为止所拥有的是:

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

I am debating on doing something like an extension or something to make this easier, but if the performance sucks or there is a better way, i would like to know. 我正在辩论做类似扩展的事情或使它更容易的事情,但是如果性能不好或有更好的方法,我想知道。

I prefer to make a class. 我更喜欢上课。 The IL just makes an anonymous class in native that gets called the same way as a normal class, so there is no performance hit associated with it. IL只是在本机中创建一个匿名类,该匿名类的调用方式与普通类相同,因此不会对性能产生任何影响。 If you ever debug anonymous types, you'll notice the name has a long name like AnonymousTypes.Program+f__1 如果您曾经调试匿名类型,您会注意到该名称具有一个长名称,例如AnonymousTypes.Program + f__1

Creating a class improves the readability of your code IMO. 创建一个类可以提高代码IMO的可读性。

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

You can also use Tuples, but even this is still unclear: 您也可以使用Tuples,但是仍然不清楚:

    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);
    }

I just experimented a little . 我只是做了一点试验 Here's what I found: 这是我发现的:

  • Anonymous types are as good as anything else. 匿名类型与其他任何类型一样好。 I can't really say "anything," since I didn't try everything. 真的不能说“什么,”因为我没有尝试一切。 But I can tell you that they're as good as Tuple<> and concrete types. 但是我可以告诉你,它们与Tuple<>和具体类型一样好。 This is logical, because underneath the covers, the compiler actually builds types for anonymous types. 这是合乎逻辑的,因为在幕后,编译器实际上为匿名类型构建类型。 In essence, at runtime, they are just concrete types. 从本质上讲,在运行时,他们只是具体类型。
  • Your ToList call is redundant. 您的ToList呼叫是多余的。 This part's important. 这部分很重要。 It's not super relevant to your immediate question, but looking at your example, you do new [] { ... }.ToList() . 它与您的紧迫问题并不相关,但是在您的示例中,您执行new [] { ... }.ToList() This forces a loop through the array after it's created. 创建数组后,这会强制循环遍历数组。 You'd be much better off using list initialization: new List<dynamic> { ... }; 使用列表初始化会更好一些: new List<dynamic> { ... }; . That's what I used in my examples. 这就是我在示例中使用的。

I ran tests 10,000 times each for: 我针对以下各项进行了10,000次测试:

  • Anonymous type with array initializer (00:00:00.0050338 total) 带有数组初始值设定项的匿名类型(总计00:00:00.0050338)
  • Anonymous type with list initializer (00:00:00.0035599 total) 带有列表初始值设定项的匿名类型(总计00:00:00.0035599)
  • Tuple with list initializer (00:00:00.0025857 total) 具有列表初始值设定项的元组(总计00:00:00.0025857)
  • Concrete type with list initializer (00:00:00.0041538 total) 带列表初始化的具体类型(总计00:00:00.0041538)

Running them again would just mix it up. 再次运行它们只会使其混乱。 The only consistent result was that arrays were, unsurprisingly, slower than going directly to a list. 唯一一致的结果是,毫不奇怪,数组比直接转到列表要慢。


If you're going to make an extension method, you'll probably want to go with one of the latter two options. 如果要创建扩展方法,则可能需要使用后两个选项之一。 Anonymous types don't travel well outside of their scope, as I'm sure you know. 像您确定的那样,匿名类型在它们的范围之外运行不太好。 The choice is yours between concrete types and tuples. 具体类型和元组之间是您的选择。 I'd go with concrete if you're using it a lot and/or outside of the original method, and a tuple if it just needs to exist somewhere. 如果您大量使用和/或在原始方法之外使用它,我会选择混凝土,而如果它只需要存在于某个地方,我会选择一个元组。 That's really a design choice that I can't make for you. 这确实是我无法为您选择的设计选择。

Since you are talking about enriching Exceptioninformation it is worth to mention that the Exceptionclass implements a property called Data which is of type IDictionary and can be used to append additional information. 由于您是在谈论丰富Exceptioninformation,因此值得一提的是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);
    }

If you find yourself adding the same information lots of times, consider some HelperMethods that add certain information to a giving exception. 如果您发现自己多次添加相同的信息,请考虑一些将特定信息添加到给定异常的HelperMethod。 This could also take care for duplicated keys which use some sort of numeric postfix that increments like fileName_1 and so on, you get the idea. 对于使用某些数字后缀(如fileName_1递增)的重复键,这也可以加以注意。 You can also create a standartized method of outputting those Information you provided yourself. 您还可以创建一种标准的方法来输出自己提供的信息。


If you want a more Complex approach you can just simply use List but make the consumer of this list handle each kind of type. 如果您想要更复杂的方法,则可以只使用List,而让此列表的使用者处理每种类型。 Which is basically the idea behind the DebuggerTypeProxy-Atrribute 基本上是DebuggerTypeProxy-Atrribute背后的想法

So you can for example use some pattern like this: 因此,例如,您可以使用以下模式:

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

In general the only reason I can think of this whole idea to beeing valid is some convenient debuggint/loggin approach. 通常,我认为整个想法有效的唯一原因是一些方便的debuggint / loggin方法。 Anything else should really use strong typing. 其他任何事情都应该真正使用强类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM