2009-09-10 61 views
11

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

因此,举例来说,我有:

string x = DoFoo(); 

是否有可能进行一些魔术,使DoFoo不执行,直到我“用” X?

回答

17

您可以使用lambda表达式/代表:

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

之后你可以调用doit就像一个方法:

string x = doit(); 

我认为你可以得到最接近的是这样的:

Lazy<string> x = DoFoo; 

string y = x; // "use" x 

有了类似这样的Lazy<T>定义(未经测试):

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<T>的类型,所以不能将其匹配到隐式转换运算符。我们需要显式声明委托的类型,这使得赋值语句更详细:

// 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); 
+0

但除了额外的间接层之外,“string x = doit()'”与string x = DoFoo()'“有什么不同? – LukeH 2009-09-10 01:14:27

+0

它不是。我没有读到这个问题。将在第二秒内改进答案... – dtb 2009-09-10 01:15:38

+0

在x被“使用”之前,仍然会调用“DoFoo()”。 – 2009-09-10 01:15:58

0

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

- 编辑

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

例如,如果你想让它'的ToString()调用的时候被调用,您可以随时继承类并在那里实现你的功能(但这将是非常不直观的恕我直言)。

1

不是传递一个字符串X的,传递采购你的字符串

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

你漂亮的委托很多描述LINQ的行动。 linq查询描述了如何获取数据,但只有在迭代查询时才会检索数据(调用DoFunc)。考虑如果您可以将您的设计更改为接受IQueryable<string>,而您需要string

3

虽然它有点脏,你总是可以使用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()); 
} 
6

一种选择是使用Lazy<T>类,以前从并行扩展库现在.Net框架4.0的一部分。

它可以让你在一个线程知道地拖延处理数据。

+0

我更喜欢使用系统类来这样做。但是,系统类没有实现隐式运算符,这促使我搜索原因。我发现[this](http://netvignettes.wordpress.com/2011/04/24/implicit-conversion-operators-are-bad/),这就解释了原因。 – 2014-09-24 21:54:22