可变的值类型包装器,传递给迭代器

我正在编写一个需要传递可变整数的迭代器。

public IEnumerable Foo(ref int valueThatMeansSomething) { // Stuff yield return ...; } 

这让我知道“错误476迭代器不能有ref或out参数”。

我需要的是在迭代器中修改这个整数值,并由迭代器的调用者使用。 换句话说,无论上面的调用Foo()想要知道valueThatMeansSomethingFoo()的结束值都可以使用它本身。 真的,我想要一个引用类型的整数,而不是值类型。

我唯一能想到的是写一个封装了我的整数的类,允许我修改它。

 public class ValueWrapper where T : struct { public ValueWrapper(T item) { this.Item = item; } public T Item { get; set; } } 

所以:

 ValueWrapper w = new ValueWrapper(0); foreach(T item in Foo(w)) { // Do stuff } if (w.Item < 0) { /* Do stuff */ } 

BCL中是否有任何类或机制来处理这个问题? 上面提出的ValueWrapper任何缺陷?

(我的实际使用比上面的例子更复杂,因此处理调用Foo() foreach循环中的变量不是一个选项。期间。)

不,我非常有信心BCL中没有任何东西可以做到这一点。 你最好的选择正是你提出的我想的。 ValueWrapper的实现确实不需要比你提出的更复杂。

当然,它不能保证是线程安全的,但如果你需要,你可以简单地将自动属性转换为带有支持变量的标准属性,并将该字段标记为volatile (以确保该值是最新的一直)。

如果您只需要写入值,那么另一种技术将是:

 public IEnumerable Foo(Action setter) { ... } int value = 0; foreach(var x in Foo(x => {value=x;}) { ... } 

巧合的是,我将在7月份的博客中对迭代器块有如此多的愚蠢限制的原因进行系列研究。 “为什么没有参考参数?” 将在系列的早期。

http://blogs.msdn.com/ericlippert/archive/tags/Iterators/default.aspx

我一直认为BCL真的应该有一个类和接口类似如下:

 public delegate void ActByRef (ref T1 p1);
 public delegate void ActByRefRef (ref T1 p1,ref T2 p2);
公共接口IReadWriteActUpon 
 {
   T值{得; 组;}
   void ActUpon(ActByRef  proc);
   void ActUpon (ActByRefRef  proc, 
                            ref TExtraparam ExtraParam);
 }

 public sealed class MutableWrapper :IReadWrite 
 {
  公共T值;
   public MutableWrapper(T value){this.Value = value;  }
   T IReadWriteActUpon  .Value {get {return this.Value;} set {this.Value = value;}}
   public void ActUpon(ActByRef  proc)
   {
     proc(ref Value);
   }
   public void ActUpon (ActByRefRef  proc, 
                            ref TExtraparam ExtraParam)
   {
     proc(ref Value,ref ExtraParam);
   }
 }

尽管许多人本能地将字段包装在自动属性中,但字段通常允许更清晰,更有效的代码,尤其是在使用值类型时。 在许多情况下,通过使用属性可以获得的增加的封装在高效和语义上可能是值得的,但是当类型的整个目的是要完全暴露和可变的状态的类对象时,这种封装是适得其反的。

包含该接口不是因为MutableWrapper许多用户想要使用该接口,而是因为IReadWriteActUpon在各种情况下都有用,其中一些需要封装,有人MutableWrapper一个实例可能希望将其传递给代码,该代码旨在处理封装在IReadWriteActUpon接口中的数据。