Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 您能否在自己的初始化行中使用变量(字典中的tryGetorels)?_C#_Linq_Dictionary - Fatal编程技术网

C# 您能否在自己的初始化行中使用变量(字典中的tryGetorels)?

C# 您能否在自己的初始化行中使用变量(字典中的tryGetorels)?,c#,linq,dictionary,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 =

考虑以下代码:

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;
    });
}
private Dictionary createTradersFor(IEnumerable设置)
{
var traderSet=新字典();
返回设置。ToDictionary(s=>s,s=>
{
var key=Tuple.Create(s.gateway,s.broker);
Trader Trader=traderSet.TryGetValue(输入,输出Trader)
交易者
:traderSet[key]=新交易者(s.gateway,s.broker);
回报交易者;
});
}
我特别讨论的是在闭包中初始化trader变量,它在实例化的同一行中使用自身


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

保证是一个强有力的词,但它非常非常,将来它不太可能停止编译-语言团队努力保持向后兼容性,除非出现巨大的范式转换(即从VB6到第一个VB.NET),否则该代码应该继续构建良好

事实上,我认为这是一个很好的技巧,但我花了一些时间才看到TryGetValue被用于三元操作(其他人也有同样的问题),因此您可能在这里保存了一行代码(将交易员声明移动一行),但您以后可能需要支付额外的维护成本(或继承此代码的人),所以也许你应该重新考虑分开声明

Trader trader;
trader = traderSet.TryGetValue(key, out trader) ?
...

除了看起来很奇怪之外,从技术上讲,它没有什么问题。
首先,将执行
trader
的声明,因此存在一个没有赋值的trader对象。 其次,计算
TryGetValue
部分并返回true或false。如果返回true,则将返回现在分配的
交易员
。如果返回false,则创建一个新的交易者,并通过赋值操作将其添加到字典中。指定操作的结果是指定给的对象的值。这就是新的交易者。 第三,三元运算符的结果将被返回并分配给
交易员

这不太可能在将来改变,因为改变这样一个语句的求值顺序是一个非常突破性的改变

更新:
因为它看起来很奇怪,我不会用它。我将通过为
IDictionary
创建一个名为
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;
}
这是非常干净的而且比你的奇形怪状的方法还要短

顺便说一句:你可以用这个来代替。这个类已经有了一个方法
GetOrAdd
,并且具有线程安全的优点

Trader trader = traderSet.TryGetValue(key, out trader)
    ? trader
    : traderSet[key] = new Trader(s.gateway, s.broker);
vs


我也看不出您所做的有任何错误,尽管我不确定它是否比直接的替代方案更好,这种替代方案不需要未来的程序员来计算代码的功能。

这是现在编译的吗?TryGetValue返回布尔值,交易者类型为trader。对我来说,这看起来像是类型不匹配。这是可以编译的,因为完整的三元运算符的结果被分配给
trader
。三元运算符的结果无疑是
Trader
类型。唯一的缺点是,由于
Trader
变量尚未声明,因此您无法在该行获得intellisense。这有点让人困惑,是扩展方法的好主意
Trader trader = traderSet.TryGetValue(key, out trader)
    ? trader
    : traderSet[key] = new Trader(s.gateway, s.broker);
Trader trader;
if (!traderSet.TryGetValue(key, out trader)) {
    trader = traderSet[key] = new Trader(s.gateway, s.broker);
}