C#局部数组IReadOnlyCollection/IReadOnlyList优化对象创建

C#局部数组IReadOnlyCollection/IReadOnlyList优化对象创建,c#,readonly,C#,Readonly,以下三种方法是否具有等效的垃圾收集行为#1将是一个延伸,但今天的C#编译器是否足够聪明,能够在每次调用该方法时优化#2中的对象创建?我特别不想将数组初始化提升到方法之外 public Boolean IsRgb1(string color) { string[] colors = { "red", "green", "blue" }; return colors.Contains(color); } public Boolean

以下三种方法是否具有等效的垃圾收集行为#1将是一个延伸,但今天的C#编译器是否足够聪明,能够在每次调用该方法时优化#2中的对象创建?我特别不想将数组初始化提升到方法之外

    public Boolean IsRgb1(string color)
    {
        string[] colors = { "red", "green", "blue" };
        return colors.Contains(color);
    }

    public Boolean IsRgb2(string color)
    {
        IReadOnlyCollection<string> colors = new[] { "red", "green", "blue" };
        return colors.Contains(color);
    }

    public Boolean IsRgb3(string color)
    {
        switch(color)
        {
            case "red":
            case "green":
            case "blue":
                return true;
            default:
                return false;
        }
    }
公共布尔值ISRG1(字符串颜色)
{
字符串[]颜色={“红色”、“绿色”、“蓝色”};
返回颜色。包含(颜色);
}
公共布尔值IsRgb2(字符串颜色)
{
IReadOnlyCollection colors=新[]{“红色”、“绿色”、“蓝色”};
返回颜色。包含(颜色);
}
公共布尔值IsRgb3(字符串颜色)
{
开关(彩色)
{
案例“红色”:
案例“绿色”:
案例“蓝色”:
返回true;
违约:
返回false;
}
}

没有与这些类型相关的编译器魔法。每次调用时,始终在Rgb1和Rgb2中创建一个数组

数组声明简写语法

string[] colors = { "red", "green", "blue" };
与相同(显示“推断语法”)

基本规则是:
new
始终创建新对象/实例。要仅创建(数组)对象一次,请仅创建一次。然后可以使用成员/字段共享单个阵列实例。这种“提升”必须手动完成

在这两种情况下,Contains都来自
IEnumerable
,因为
T[]
IReadOnlyList
都是IEnumerable1的子类型,并且符合LINQ Contains扩展方法的条件。将使用相同的IEnumerable Contains实现(LINQ To Objects),应用于数组的任何专门化都应适用于这两种情况

Rgb3案例完全避免了数组创建,避免了一些方法调用,并避免了执行包含“循环”逻辑的广义集合的开销。它将是最快的——如果/在这样重要的地方——仅仅因为它做的事情最少

字符串的简单switch语句可以被视为编写一系列比较相同值的
if..else if..
的替代方法。在这种情况下,没有为每个方法调用创建新对象:字符串文本已被插入,显然没有新数组

另一方面,简单地考虑使用一个表达式:

 return color == "red" || color == "green" || color == "blue";
1由于类型继承令人困惑,这里有一个小摘录:

T[]->IEnumerable(包含为扩展方法)
->IList->ICollection(包含在接口中)->IEnumerable
->IReadOnlyList->IEnumerable
->IReadOnlyCollection->IEnumerable

由于
T[]
IReadOnlyList
的子类型,因此Rgb2中的赋值导致了隐式向上转换-变量仍然命名新创建的数组对象。在编译时选择
IEnumerable.Contains
,因此Rgb1和Rgb2方法都将在原始创建的数组对象上使用扩展方法
IEnumerable.Contains
。要使用
ICollection.Contains
将需要
((IList)颜色).Contains(..)
或类似颜色。

在这种情况下,我可能会选择
新的哈希集(StringComparer.OrdinalingOreCase)
;使用不区分大小写的比较进行快速查找。@MetroSmurf由于常数开销小得多,字符串比较会更快(甚至包含也可能更快)。同意使用少量数据。对于较大的集合,请使用Hashset。无论如何,这只是另一种选择。@MetroSmurf肯定;对于“正常大小”的颜色名称调色板,这将是一个值得考虑的问题!添加到集合中通常也比较容易,因为集合的设计允许任意大小。@MetroSmurf对于较大的集合,不,您可能仍然不需要处理哈希集。如果switch语句有足够的大小写标签来提高性能,编译器将在幕后生成并调用哈希函数。你自己试试看。
// One array created and stored for later use ..
private static string[] Colors = { "red", "green", "blue" };
// .. independent of number of times this method is called
public Boolean IsRgb(string color)
{
    return Colors.Contains(color);
}
 return color == "red" || color == "green" || color == "blue";