带有可为空的ref参数的委托,该参数可能为空

本文关键字:参数 ref | 更新日期: 2023-09-27 18:02:02

我知道这很荒谬…但这里有一个演示:

class Foo
{
    // A lot of data in the nullable class foo.
}
class bar
{
    public delegate void FooHandler(object sender, ref Foo f);
    public event FooHandler FooChanged;
}

问题是我想在事件处理程序中将'f'设置为null,但我不能将null作为ref传递。我尝试了这个:

    public delegate void FooHandler(object sender, ref Foo? f);

但是Foo是可空的,所以这不起作用。然后,我尝试修改处理程序的invoke方法,并设置要传递的虚拟空项,这也不起作用。我尝试使用out代替ref, out不需要初始化变量,并且编译但没有运行。

这真的很奇怪,我从来没有见过这样的事情。我可以将Foo类更改为非空的,这样我就可以将其实现为空,或者我可以添加自己的标志Foo。HasValue和这样做…但是没有办法在不改变Foo类的情况下做到这一点吗?

带有可为空的ref参数的委托,该参数可能为空

在c#中,如果没有对变量的实际引用,则不可能调用带有ref参数的方法。

例如,如果你有一个方法

void DoWork(ref Foo foo)
{
    foo = new Foo();
}

你可以做

Foo foo = null;
DoWork(ref foo);  // works

但是你不能做

DoWork(ref null); // does not compile
DoWork(null);     // does not compile

如果您想使ref参数成为可选的,您必须提供两个重载:

void DoWork();
void DoWork(ref Foo x);

这绝对可以工作,尽管它非常不习惯…你说你已经试过了,但是失败了,但是没有代码,我们就不知道你做错了什么。

忽略事件部分和第一个参数,这两个都是不相关的,这里有一个完整的示例,显示outref参数都工作得很好:

using System;
delegate void ByRef(ref string x);
delegate void ByOut(out string x);
class Test
{
    static void Main()
    {
        ByRef r = (ref string x) => { x = null; };
        string tmp = "Not null";
        r(ref tmp);
        Console.WriteLine(tmp == null); // True
        ByOut o = (out string x) => { x = null; };
        string tmp2;
        o(out tmp2);
        Console.WriteLine(tmp2 == null); // True
    }
}