我正在寻找一种在C#中创建值列表的快捷方法.在Java中,我经常使用下面的代码段:
List<String> l = Arrays.asList("test1","test2","test3");
Run Code Online (Sandbox Code Playgroud)
除了下面明显的一个之外,C#中是否还有其他等价物?
IList<string> l = new List<string>(new string[] {"test1","test2","test3"});
Run Code Online (Sandbox Code Playgroud) 更新:@usr指出我错误地认为Lazy<T>默认的线程安全模式是LazyThreadSafetyMode.PublicationOnly......
我想懒洋洋地通过async工厂方法计算一个值(即它返回Task<T>)并在成功时缓存它.在例外情况下,我想让我可以使用它.我不然而,要堕入了异常缓存的行为是Lazy<T>在其默认模式(LazyThreadSafetyMode.ExecutionAndPublication)
异常缓存:使用工厂方法时,会缓存异常.也就是说,如果工厂方法在线程第一次尝试访问Lazy对象的Value属性时抛出异常,则每次后续尝试都会抛出相同的异常.这确保了对Value属性的每次调用都会产生相同的结果,并避免在不同的线程获得不同结果时可能出现的细微错误.懒惰代表一个实际的T,否则它将在某些早期点(通常在启动期间)初始化.在那个早期点失败通常是致命的.如果存在可恢复故障的可能性,我们建议您将重试逻辑构建到初始化例程(在本例中为工厂方法),就像您不使用延迟初始化一样.
Stephen Toub的AsyncLazy课程和写作似乎恰到好处:
public class AsyncLazy<T> : Lazy<Task<T>>
{
public AsyncLazy(Func<Task<T>> taskFactory) :
base(() => Task.Factory.StartNew(() => taskFactory()).Unwrap())
{ }
public TaskAwaiter<T> GetAwaiter() { return Value.GetAwaiter(); }
}
Run Code Online (Sandbox Code Playgroud)
然而,这实际上与默认行为相同Lazy<T>- 如果出现问题,则不会重试.
我正在寻找一个Task<T>兼容的等价物Lazy<T>(Func<T>, LazyThreadSafetyMode.PublicationOnly),即它应该按照指定的行为: -
锁定的替代方法在某些情况下,您可能希望避免Lazy对象的默认锁定行为的开销.在极少数情况下,可能存在死锁的可能性.在这种情况下,您可以使用Lazy(LazyThreadSafetyMode)或Lazy(Func,LazyThreadSafetyMode)构造函数,并指定LazyThreadSafetyMode.PublicationOnly.如果线程同时调用Value属性,这使Lazy对象能够在多个线程中的每个线程上创建一个延迟初始化对象的副本.Lazy对象确保所有线程使用延迟初始化对象的相同实例并丢弃未使用的实例.因此,降低锁定开销的成本是您的程序有时可能会创建并丢弃昂贵对象的额外副本.在大多数情况下,这不太可能.Lazy(LazyThreadSafetyMode)和Lazy(Func,LazyThreadSafetyMode)构造函数的示例演示了此行为.
重要
指定PublicationOnly时,即使指定了工厂方法,也不会缓存异常.
是否有任何FCL Nito.AsyncEx或类似的结构可能适合这里?如果没有这个,任何人都可以看到一种优雅的方式来控制"尝试进行中"位(我很好,每个调用者以与Lazy<T>(... 相同的方式进行自己的尝试(LazyThreadSafetyMode.PublicationOnly))并且仍然具有该缓存管理封装整齐?