C#。为ref扩展方法返回ref委托

4
我有以下扩展方法来监控一个变量,并等待直到它具有给定的预期值:
        public static async Task AwaitForValue<T>(this Func<T> valueGetter, T expectedValue, int? millisecondsToAwaitBetweenChecks = null, int? maxMillisecondsToAwait = null) 
            where T : struct
        {
            var timeToAwait = millisecondsToAwaitBetweenChecks ?? 20;
            if (maxMillisecondsToAwait.HasValue)
            {
                var stopWatch = new Stopwatch();
                stopWatch.Start();
                while (!valueGetter().Equals(expectedValue) || stopWatch.ElapsedMilliseconds >= maxMillisecondsToAwait)
                {
                    await Task.Delay(timeToAwait);
                }
            }
            else
            {
                while (!valueGetter().Equals(expectedValue))
                {
                    await Task.Delay(timeToAwait);
                }
            }    
         }

它很正常地工作:

class Foo
        {
            private bool _flag;

            public async void DoWork()
            {
                Task.Run(() =>
                {
                    Thread.Sleep(5000);
                    _flag = true;
                });
                await new Func<bool>(() => _flag).AwaitForValue(true);
                Console.WriteLine(_flag);
            }
         }

我想定义一个ref扩展方法,它可以提供一个委托来返回ref变量的当前值,类似于:

public delegate ref T RefFunc<T>();

这种方式可以扩展RefFunc<T>而不是Func<T>,并且可以像下面这样使用:

_flag.ToRefFunc().AwaitForValue(true);

问题在于我找不到一种合适的方式来正确定义ToRefFunc<T>(this ref T value);,因为lambda表达式中不允许使用ref。是否有一种方法来定义以下方法?
public static RefFunc<T> ToRefFunc<T>(this ref T value) where T : struct
{
     //todo some day
}

理想情况下,它应该看起来像这样:


public static RefFunc<T> ToRefFunc<T>(this ref T value) where T : struct => new RefFunc<T>(() => value);

任何帮助都将不胜感激

编辑

问题并不在于是否允许使用ref扩展方法,可以从“重复”问题中参见此处

编辑2 匿名委托语法也不起作用:

public static RefFunc<T> ToRefFunc<T>(this ref T value) where T: struct
{
    return delegate { return value; }; 
}

我收到的错误信息是:无法在匿名方法、Lambda表达式、查询表达式或局部函数中使用ref、out或in参数'value'


1
在C# 7.2中,只要扩展的是结构体,你就可以定义ref扩展方法。@Joelius - taquion
1
那我就收回之前的话了 :) 不知道这个。文档页面上没提到或者是我眼瞎了?在这里也没有找到。有关于此的文档页面吗? - Joelius
我已在文档页面上打开了一个问题:此处 - taquion
1
虽然不完全符合您的要求,但您可以创建一个带有AwaitForValue()函数的ObservableBase类。这将有助于解决在尝试访问任意作用域值类型时可能遇到的任何范围问题。您可以使用类似AwaitForValue(nameof(_flag), true)的语法。 - chill94
1
@taquion:哦,抱歉,我误解了,以为你试图定义一个带有 ref 返回类型的匿名函数。你是在尝试关闭调用范围内的 ref 参数。这是不允许的。 - Ben Voigt
显示剩余9条评论
1个回答

1
一个ref参数是只能在函数内部使用,不能“保存到以后再用”的东西。这是因为ref参数无法保持它所引用的变量的生命。
考虑使用引用类型(C#术语:class)来保存您的数据。然后,您可以拥有任意数量的句柄,并且它们将参与垃圾回收(对象生命周期、内存压缩等)。不幸的是,这需要更改变量的所有用户——它不是可以在现有对象模型中修改数据的东西。

有道理...嗯...我希望能找到一种方法...谢谢,伙计! - taquion

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