使用可为null的可为空参数的参数进行委托

时间:2011-07-14 20:43:31

标签: c# events delegates nullable

我知道这很荒谬......但是这是一个演示:

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方法并设置一个虚拟的null项来传递,这也无效。我尝试使用out而不是ref因为out不需要初始化变量,并且编译但是没有运行。

这真的很奇怪,我从来没有见过这样的东西。我可以将Foo类更改为不可为空,这样我就可以将它实现为Nullable,或者我可以添加自己的标志Foo.HasValue并按这样做...但是如果不改变Foo类就没有办法做到这一点?

2 个答案:

答案 0 :(得分:4)

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

同样适用于代表/活动。

答案 1 :(得分:3)

这可以绝对工作,虽然它非常非惯用...你说你已经尝试过但失败了,但没有代码,我们就不会知道你做错了什么

忽略事件部分和第一个参数,两者都不相关,这是一个完整的示例,显示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

    }
}