3

需要明确的是,我想要指针的行为,这个问题的目的是生成干净、可读的代码。

我有一些代码包含检查多个Dictionary.TryGetValue调用结果的条件。如果它可以通过一次调用检索所有必需的对象会更干净,所以我想编写一个扩展,允许我执行以下操作:

Dictionary<string, string> myDictionary; // Initialized somewhere

string x, y, z;
bool foundAllEntries = myDictionary.TryGetValues({"xvalue", out x}, {"yvalue", out y}, 
    {"zvalue", out z});
if (foundAllEntries)
    ; // Do something with x, y, and z

但是,我想不出一种将扩展方法引用传递给将保存输出的对象的方法。这似乎应该是非常基本的东西。

如何在对象中存储对本地引用的引用?

请注意,这个问题并不是要求实现 TryGetValues 函数的替代方法。有很多方法可以让这个“工作”,但没有一种方法能像我尝试采用的方法那样生成干净的代码。

4

2 回答 2

9

这似乎应该是非常基本的东西。

它不仅不是基本的,而且是完全不可能的:无法用refor修饰数据类型out——这些修饰符仅适用于形式方法参数。换句话说,不存在“参考变量”或“输出变量”之类的东西;语言中只有“参考参数”和“输出参数”。

此外,您不能将输出或引用参数作为可变长度参数列表(即params部分)的一部分传递,因此该方法也不起作用。

有很多方法可以让这个“工作”,但没有一种方法能像我尝试采用的方法那样生成干净的代码。

奇怪的是,以上内容并不意味着您无法实现您正在尝试实现的方案,如果您应用代理设计模式,则代码几乎与原始代码一样干净。诀窍是链接方法调用,并为结果提供隐式转换运算符,如下所示:

class MyMap {
    internal IDictionary<string,string> dict = ...
    public ItemGetterResult TryGetValues {
        get {
            return new ItemGetterResult(this, true);
        }
    }
}

class ItemGetterResult {
    private readonly MyMap map;
    private bool IsSuccessful {get;set;}
    internal ItemGetterResult(MyMap theMap, bool successFlag) {
        map = theMap;
        IsSuccessful = successFlag;
    }
    public static implicit operator bool(ItemGetterResult r) {
        return r.IsSuccessful;
    }
    public ItemGetterResult Get(string key, out string val) {
        return new ItemGetterResult(
            map
        ,   this.IsSuccessful && map.dict.TryGetValue(key, out val)
        );
    }
}

现在调用看起来像这样:

bool foundAllEntries = myDictionary.TryGetValues
    .Get("xvalue", out x)
    .Get("yvalue", out y)
    .Get("zvalue", out z);
于 2014-12-31T22:30:47.260 回答
0

您可以创建一个可变Reference类型:

public class Reference<T>
{
    public T Value;
}

/* declaration */
bool TryGetValues(
    this Dictionary<K,V> dict,
    params Tuple<K, Reference<V>>[] requests)

/* call site */
var x = new Reference<string>();
var y = new Reference<string>();
var z = new Reference<string>();
bool foundAllEntries = myDictionary.TryGetValues(
    Tuple.Create("xvalue", x),
    Tuple.Create("yvalue", y), 
    Tuple.Create("zvalue", z));
于 2014-12-31T22:38:14.710 回答