你可以在他们自己的初始化行中使用变量(字典中的tryGetOrElse)吗?

Gro*_*ozz 4 c# linq dictionary

请考虑以下代码:

private Dictionary<RobotSettings, Trader> createTradersFor(IEnumerable<RobotSettings> settings)
{
    var traderSet = new Dictionary<Tuple<IGateway, IBroker>, Trader>();

    return settings.ToDictionary(s => s, s =>
    {
        var key = Tuple.Create(s.gateway, s.broker);

        Trader trader = traderSet.TryGetValue(key, out trader)
            ? trader
            : traderSet[key] = new Trader(s.gateway, s.broker);
        return trader;
    });
}
Run Code Online (Sandbox Code Playgroud)

我正在谈论闭包中的trader变量的初始化,它在实例化的同一行中使用它自己.

我最近一直在使用这种处理字典的模式,因为我真的不喜欢未初始化的变量:)并且想知道这是否有保证将来编译.

Dan*_*rth 5

除了看起来很奇怪之外,它没有任何问题 - 技术上.
首先,trader将执行声明,因此存在没有赋值的Trader对象.其次,TryGetValue评估零件并返回true或false.如果返回true,则返回现在分配的trader内容.如果返回false,则创建新的Trader并通过赋值操作将其添加到字典中.赋值操作的结果是分配给的对象的值.那是新的交易员.第三,将返回三元运算符的结果并将其分配给trader.

这种情况不太可能在未来发生变化,因为改变这样一个声明的评估顺序是一个非常突破性的变化.

更新:
因为它看起来很奇怪,我不会用它.我会通过为IDictionary<TKey, TValue>被调用创建一个扩展方法来解决这个问题GetOrAdd.
它可能看起来像这样:

public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dict,
                                            TKey key, Func<TKey, TValue> creator)
{
    TValue value;
    if(!dict.TryGetValue(key, out value))
    {
        value = creator(key);
        dict.Add(key, value);
    }
    return value;
}
Run Code Online (Sandbox Code Playgroud)

你会这样称呼它:

var trader = traderSet.GetOrAdd(key, k => new Trader(s.gateway, s.broker));
Run Code Online (Sandbox Code Playgroud)

这是一个更清洁,它甚至比你奇怪的方法更短.

顺便说一句:你可以用它ConcurrentDictionary<TKey, TValue>代替.这个类已经有了一个方法,GetOrAdd并且具有线程安全的好处.