C# 中的延迟执行

发布于 2024-08-04 18:43:08 字数 132 浏览 5 评论 0原文

如何在 C# 中实现自己的延迟执行机制?

例如,我有:

string x = DoFoo();

是否可以执行一些魔法,以便 DoFoo 在我“使用”x 之前不会执行?

How could I implement my own deferred execution mechanism in C#?

So for instance I have:

string x = DoFoo();

Is it possible to perform some magic so that DoFoo does not execute until I "use" x?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

江南烟雨〆相思醉 2024-08-11 18:43:08

您可以使用 lambdas/delegates:

Func<string> doit = () => DoFoo();
//  - or -
Func<string> doit = DoFoo;

稍后您可以像方法一样调用 doit

string x = doit();

我认为您可以获得的最接近的是这样的:

Lazy<string> x = DoFoo;

string y = x; // "use" x

使用 Lazy 的定义> 与此类似(未经测试):

public class Lazy<T>
{
    private readonly Func<T> func;
    private bool hasValue;
    private T value;

    public Lazy(Func<T> func)
    {
        this.func = func;
        this.hasValue = false;
    }

    public static implicit operator Lazy<T>(Func<T> func)
    {
        return new Lazy<T>(func);
    }

    public static implicit operator T(Lazy<T> lazy)
    {
        if (!lazy.hasValue)
        {
            lazy.value = lazy.func();
            lazy.hasValue = true;
        }
        return lazy.value;
    }
}

不幸的是,编译器的类型推断算法似乎无法自动推断 Func 的类型,因此无法将其与隐式转换匹配操作员。我们需要显式声明委托的类型,这使得赋值语句更加冗长:

// none of these will compile...
Lazy<string> x = DoFoo;
Lazy<string> y = () => DoFoo();
Lazy<string> z = delegate() { return DoFoo(); };

// these all work...
Lazy<string> a = (Func<string>)DoFoo;
Lazy<string> b = (Func<string>)(() => DoFoo());
Lazy<string> c = new Func<string>(DoFoo);
Lazy<string> d = new Func<string>(() => DoFoo());
Lazy<string> e = new Lazy<string>(DoFoo);
Lazy<string> f = new Lazy<string>(() => DoFoo);

You can use lambdas/delegates:

Func<string> doit = () => DoFoo();
//  - or -
Func<string> doit = DoFoo;

Later you can invoke doit just like a method:

string x = doit();

I think the closest you can get is something like this:

Lazy<string> x = DoFoo;

string y = x; // "use" x

With a definition of Lazy<T> similar to this (untested):

public class Lazy<T>
{
    private readonly Func<T> func;
    private bool hasValue;
    private T value;

    public Lazy(Func<T> func)
    {
        this.func = func;
        this.hasValue = false;
    }

    public static implicit operator Lazy<T>(Func<T> func)
    {
        return new Lazy<T>(func);
    }

    public static implicit operator T(Lazy<T> lazy)
    {
        if (!lazy.hasValue)
        {
            lazy.value = lazy.func();
            lazy.hasValue = true;
        }
        return lazy.value;
    }
}

Unfortunately, it seems that the compiler's type inferencing algorithms can't auto-infer the type of the Func<T> and so can't match it to the implicit conversion operator. We need to explicitly declare the delegate's type, which makes the assignment statements more verbose:

// none of these will compile...
Lazy<string> x = DoFoo;
Lazy<string> y = () => DoFoo();
Lazy<string> z = delegate() { return DoFoo(); };

// these all work...
Lazy<string> a = (Func<string>)DoFoo;
Lazy<string> b = (Func<string>)(() => DoFoo());
Lazy<string> c = new Func<string>(DoFoo);
Lazy<string> d = new Func<string>(() => DoFoo());
Lazy<string> e = new Lazy<string>(DoFoo);
Lazy<string> f = new Lazy<string>(() => DoFoo);
只是我以为 2024-08-11 18:43:08

一种选择是使用 Lazy 类,该类以前来自并行扩展库,现在是 .Net Framework 4.0 的一部分。

它允许您以线程感知的方式延迟处理数据。

One option is to use the Lazy<T> class, formerly from the parallel extensions library now a part of the .Net Framework 4.0.

It allows you to delay process data in a thread aware manner.

挽容 2024-08-11 18:43:08

虽然它有点脏,但你总是可以使用yield关键字:

public IEnumerable<int> DoFoo() {
   Console.WriteLine("doing foo");
   yield return 10;
}

[Test]
public void TestMethod()
{
    var x = DoFoo();
    Console.WriteLine("foo aquired?");
    Console.WriteLine(x.First());
}

While it's somewhat dirty you could always use the yield keyword:

public IEnumerable<int> DoFoo() {
   Console.WriteLine("doing foo");
   yield return 10;
}

[Test]
public void TestMethod()
{
    var x = DoFoo();
    Console.WriteLine("foo aquired?");
    Console.WriteLine(x.First());
}
温柔一刀 2024-08-11 18:43:08

不要传递字符串 x,而是传递一个为您获取字符串的委托

Func<String> fooFunc=()=>DoFoo();

Instead of passing a string x, pass a delegate that procures you a string

Func<String> fooFunc=()=>DoFoo();
寒江雪… 2024-08-11 18:43:08

为什么不直接调用“DoFoo()”直到你想要调用呢?

-- 编辑

我的意思是,“使用”是什么意思

例如,如果您希望在调用“.ToString()”时调用它,您始终可以继承该类并在那里实现您的函数(但这将非常不直观恕我直言)。

Why not just not call 'DoFoo()' until you want to?

-- Edit

I mean, what do you mean "use"

For example, if you want it to be called when '.ToString()' called, you can always inherit the class and implement your function there (but this would be quite unintuitive IMHO).

孤芳又自赏 2024-08-11 18:43:08

您几乎描述了 LINQ 的实际应用。 linq 查询描述了如何获取数据,但只有在迭代查询时才会检索数据(调用 DoFunc)。考虑是否可以更改设计以接受 IQueryable< string>,您需要一个字符串

You pretty much describe LINQ in action. A linq query describes how to obtain the data, but data is retrieved (DoFunc is called) only when the query is iterated. Consider if you can change your design to accept IQueryable<string> where you need a string.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文