我可以存储对本地参考的引用吗?

时间:2014-12-31 22:11:40

标签: c# reference pointer-to-pointer

要清楚,我想要一个指向指针的行为,这个问题的目的是生成干净,可读的代码。

我有一些代码包含检查多个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函数的替代方法。我有很多方法可以使这个'工作',但是没有一个方法可以生成像我那样干净的代码。我试图采取。

2 个答案:

答案 0 :(得分:9)

  

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

不仅不是基本的,它是完全不可能的:没有办法用refout来装饰数据类型 - 这些修饰符仅适用于形式方法参数。换句话说,没有“参考变量”或“输出变量”这样的东西;语言中只有“参考参数”和“输出参数”。

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

  

我可以通过多种方式实现“工作”,但没有一种方法可以像我正在尝试的那样生成干净的代码。

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

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);

答案 1 :(得分: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));