我可以将本地引用的引用存储起来吗?

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函数。 我可以用很多方法使这个“工作”,但没有一种方法能够生成像我尝试采取的方法一样干净的代码。


5
“扩展方法引用”是什么意思还不清楚。你提供的代码肯定适用于 TryGetValues 的任何实现……对于它的签名,我不清楚你期望它是什么样子。(我可以想到一些替代方法可以工作,但你说你不想要那些方法,所以我只能说无论你做什么,你目前的代码都无法编译。) - Jon Skeet
3
如果您在问能否使用 outref 参数与引用类型一起使用,那么答案是肯定的。但我无法确定您正在尝试实现哪个方法签名,这使得很难确定您真正想要的是否得到了支持。先忘掉实现 - 确定下方法签名。 (个人建议使用方法链而不是单个调用,但嘿...) - Jon Skeet
2
好的,所以你正在尝试在Pair中使用out - 这是行不通的,因为out不是类型本身的一部分,无法在类型参数中指定它。 (它是一个参数修饰符,而不是类型的一部分。)这肯定不会让我困扰 - 但正如我所说,我也不会尝试以这种方式解决问题。 - Jon Skeet
5
我会使用的语法最终会得到类似于 if (dict.TryGetValues("xvalue", out x).And("yvalue", out y).And("zvalue", out z).AllFound) 的东西。 - Jon Skeet
1
@Mike 用一个泛型替换string - Patrick Hofman
显示剩余4条评论
2个回答

9
这似乎是非常基础的内容。但事实上,它是不可能的:没有办法用ref或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);

对于隐式转换为布尔值,使用“+1”非常方便。 - Mike Christensen
一个索引器可能会使它更加时髦;p - leppie

0
您可以创建一个可变的引用类型:
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));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接