【问题标题】:Delegate with nullable ref parameter that could be null具有可为空的 ref 参数的委托,该参数可能为空
【发布时间】:2011-07-14 20:43:30
【问题描述】:

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

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 是可以为空的,所以这是行不通的。然后我尝试修改处理程序的调用方法并设置一个要传递的虚拟空项,这也不起作用。我尝试使用 out 而不是 ref 因为 out 不需要初始化变量,并且编译但没有运行。

这真的很奇怪,我从未真正见过这样的事情。我可以将 Foo 类更改为不可为空,因此我可以将其实现为 Nullable,或者我可以添加我自己的标志 Foo.HasValue 并这样做......但是如果不更改 Foo 类就没有办法做到这一点?

【问题讨论】:

  • 一般事件模式是FooHandler(object sender, EventArgs e)。您想通过更改此模式并将事件参数设置为 null 来解决什么问题?
  • 这绝对可以工作 - 但您还没有向我们提供您尝试过的任何选项的完整代码。我将发布一个工作示例,但这当然不会显示有什么区别......
  • 类根据定义是引用类型,因此已经可以为空,因此将它们包装在可空类型中是没有意义的。 Nullable<T> 结构旨在允许值类型(根据定义,非空)表示空值。
  • @Paolo:我认为说值类型“根据定义不为空”是不明智的。根据定义,值类型按值复制。不要求值类型不可为空;也没有要求引用类型必须可以为空。如果有人想反常,可以构建一个具有可空值类型和不可空引用类型的类型系统。

标签: c# events delegates nullable


【解决方案1】:

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

这同样适用于委托/事件。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 你说得对,我应该发布更多代码,但我认为这是一个理论问题,而不是编码错误。事实证明这是一个严重的错误,因为这是一个编码错误,我在同一行上得到了一个单独的空引用,并假设它是参数。
    猜你喜欢
    • 2010-12-25
    • 2016-08-07
    • 1970-01-01
    • 2018-07-26
    • 1970-01-01
    • 2017-06-14
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    相关资源
    最近更新 更多