繁体   English   中英

表达体方法性能

[英]Expression Bodied method performance

我想知道返回静态列表的表达式主体方法或使用缓存列表变量时是否存在性能差异。

考虑这个代码

// expression body
private static List<Guid> GetList() => new()
{
    new Guid("f93b8c93-3084-4087-8727-dad436fe5b76"),
    new Guid("6894046e-1deb-4128-b639-aa472f7f95d3")
    // many more 
};

vs缓存列表然后返回它

// create the list
private static readonly List<Guid> CacheList = new()
{
    new Guid("f93b8c93-3084-4087-8727-dad436fe5b76"),
    new Guid("6894046e-1deb-4128-b639-aa472f7f95d3")
    // many more
};

// return the list
private static List<Guid> GetList()
{
    return CacheList;
}

是否只在第一次调用 GetList() 时才编译表达式体方法结果,还是每次调用 GetList() 方法时都会编译表达式?

谢谢

private static List<Guid> GetList() => new()
{
  new Guid("f93b8c93-3084-4087-8727-dad436fe5b76"),
  new Guid("6894046e-1deb-4128-b639-aa472f7f95d3")
  // many more 
};

这将在您每次调用GetList函数时创建一个新列表。 即,在调用GetList之后对该列表进行的GetList将仅适用于该实例,而不适用于调用GetList函数的其他实例。

private static List<Guid> GetList()
{
  return CacheList;
}

此示例中的GetList方法将为调用此函数的每个人返回相同的实例。 即,修改此列表会将更改应用于调用此函数并请求该特定实例的任何人。

在性能方面,正则函数和表达式体没有区别。 它是 C# 6.0 中添加的纯语法糖。 这意味着它编译为相同的 IL 代码并且性能绝对没有差异。

除了在堆上newing List 并在每次调用时向其中添加项目的直接性能影响之外,所有这些列表的“副本”的影响也不太明显,稍后需要由 GC 收集这些“副本”。

但除了性能,还有另一个考虑

private static List<Guid> GetList() => new() ...

本质上是一个工厂方法,返回一个可变(但复制)的集合。 然后调用者可以自由地向集合中添加新元素,而不会影响任何其他可能已获得其“副本”的代码。

然而

private static readonly List<Guid> CacheList = new()
{...};

private static List<Guid> GetList()
{
    return CacheList;
}

// OR
private static List<Guid> GetList() => CacheList;

两者都返回对同一个静态共享可变集合的引用。 readonly意味着CacheList字段不可重新分配,它不会改变List<T>可变的事实)

这可能适合您的目的,因为字段和方法都是private 但是,将可变静态集合publicpublic字段或方法并不是一个好的做法。 考虑一个调用者:

var theList = myClass.GetList();
theList.Add(Guid.NewGuid()); // << Mutation

此更改将影响共享CachedList所有观察者,事实上,如果多个调用者尝试更改此代码将存在线程安全问题。 因为底层字段也是静态的,对列表的更改将在进程的生命周期内持续存在,这可能会导致潜在的错误。

因此,在公开“缓存”字段时,我将始终确保这些字段是完全不可变的,例如

private static readonly IReadOnlyCollection<Guid> CacheList = new List<Guid>
{
    ...
};

// Ensure that public accessors restrict mutability
public static IReadOnlyCollection<Guid> GetList() => CacheList;

调用者将无法从共享缓存列表中添加/删除元素,因此这将同时具有线程安全性、高性能和内存效率。

暂无
暂无

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

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