【问题标题】:Using C#'s ref features on (dictionary) indexers在(字典)索引器上使用 C# 的 ref 功能
【发布时间】:2018-11-04 17:08:17
【问题描述】:

我想知道是否可以在(字典)索引器或定义 setget 访问器的属性上使用 C# 的 ref return,例如:

readonly Dictionary<string, int> dictionary = ...;


ref int v = ref dictionary["foo"];
//          ^^^^^^^^^^^^^^^^^^^^^
// CS0206: A property or indexer may not be passed as an out or ref parameter
v = 42;

是否有可能以某种方式为属性或索引器提供ref 功能(不使用反射)?如果有,怎么做?


我知道,从这个意义上说,错误消息很清楚 - 但是,我想知道哪种方法是实现其语义的最佳方式。

【问题讨论】:

  • 由于您实际上希望以延迟方式传递 setter,如果您的接口支持,您可以使用 Action&lt;int&gt; 委托。
  • @TimSchmelter:我编辑了问题:我想知道如何实现 sematics 的实现
  • 如果您想专门使用内置的Dictionary 执行此操作 - 您必须稍等片刻才能实现:github.com/dotnet/corefx/issues/20684
  • ref 在运行时被实现为指针。指针需要一个内存位置来指向。因此,属性或索引器永远无法限定,它们是方法而不是内存位置。对于普通方法参数,与 C# v1.0 ref syntax 没有其他区别,您也不能为参数传递属性或索引器。
  • @HansPassant 现在不完全正确,因为包括属性在内的方法现在可以通过引用返回值,因此某些属性(ref Something 类型)可以传递给期望 ref 参数的方法对应的类型。

标签: c# ref


【解决方案1】:

答案是否定的,因为属性(或索引器,它们是特殊属性)are actually methodsa ref to a method is a delegate

So you can useAction&lt;T&gt; 你的代码变成(未测试的代码):

readonly Dictionary<string, int> dictionary = ...;
Action<int> v = (x) => dictionary["foo"] = x;
v(42);

【讨论】:

  • 我认为这并不代表问题中正在讨论的场景,它专门谈论将ref 获取到基础价值
  • @MarcGravell 同意,我可能对这个问题的解释太多了。根据发布的代码,我假设其意图是修改基础值。
【解决方案2】:

这需要实现索引器的类型提供ref-返回在索引器中,所以不行:你不能将它与Dictionary&lt;string, int&gt;一起使用。但是有这样的事情:

class MyRefDictionary<TKey, TValue>
{
    public ref TValue this[TKey key]
    {   // not shown; an implementation that allows ref access
        get => throw new NotImplementedException();
    }
}

你确实可以这样做:

ref var val = ref dictionary[key];

请注意,数组是一种特殊情况,因为数组始终允许 ref 索引器访问,即

SomeMethod(ref arr[42]);

(数组中的索引器访问由编译器实现,而不是类型)

【讨论】:

  • 我知道使用ref return readonly-properties 来实现这一点,但是,我认为可以像数组那样实现它
  • @Unknown6656 不;那是不可能的;编译器处理数组索引器与任何其他类型的索引器非常不同 - 数组索引器有特定的 IL 指令 - 参见 ldelem / ldelem_* (获取值)vs ldelema (获取ref)跨度>
  • @Unknown6656:考虑到索引器只是方法的语法糖,可以从字面上实现以任意复杂方式获取和设置值的逻辑。现在想象一下以某种方式将其填充到 ref int 中,您应该欣赏编译器将面临的任务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
  • 1970-01-01
  • 2019-04-26
  • 1970-01-01
  • 2022-07-15
  • 2022-10-26
相关资源
最近更新 更多