可变包装纸的价值类型的通过成迭代
-
20-08-2019 - |
题
我正在写一个迭代,需要通过围绕一个可变的整数。
public IEnumerable<T> Foo(ref int valueThatMeansSomething)
{
// Stuff
yield return ...;
}
这个蚊帐是我"错误476迭代不能有ref或出的参数"。
什么我需要的是这个的整数值加以修改的迭代和可用的呼叫者的迭代器。换句话说,不论通话 Foo()
上述想知道最终价值 valueThatMeansSomething
和 Foo()
可以利用它本身。真的,我要一个整数,是参照类型不值类型。
我唯一能想到的是编写一个类封装我整数和允许我以修改它。
public class ValueWrapper<T>
where T : struct
{
public ValueWrapper(T item)
{
this.Item = item;
}
public T Item { get; set; }
}
所以:
ValueWrapper<int> w = new ValueWrapper<int>(0);
foreach(T item in Foo(w))
{
// Do stuff
}
if (w.Item < 0) { /* Do stuff */ }
是否有任何类或机制来处理这已经在BCL? 任何缺陷 ValueWrapper<T>
上述建议?
(我的实际使用更复杂的比例如上所述处理可变我的内心 foreach
循环的电话 Foo()
是不是一种选择。期。)
解决方案
不,我很确信没有什么现有的BCL可以做到这一点。你最好的选项,正是你有什么建议,我认为。执行情况 ValueWrapper
真的不需要任何更复杂的比你有什么建议。
当然,这是不能保证线的安全,但是如果你需要那你可以简单地转换自动产成为一个标准的一个背变量和标记领域的作为 volatile
(确保值是日在所有次)。
其他提示
如果你只需要编写的价值,然后用另一种技术将是:
public IEnumerable<whatever> Foo(Action<int> setter) { ... }
int value = 0;
foreach(var x in Foo(x => {value=x;}) { ... }
巧合的是,我会做一系列的原因,为什么有这么多愚蠢的限制迭代块在我的博客。"为什么没有ref参数?"将能在早期系列。
http://blogs.msdn.com/ericlippert/archive/tags/Iterators/default.aspx
我一直认为BCL真的应该具有一类和口喜欢的东西如下:
public delegate void ActByRef<T1,T2>(ref T1 p1); public delegate void ActByRefRef<T1,T2>(ref T1 p1, ref T2 p2); public interface IReadWriteActUpon<T> { T Value {get; set;} void ActUpon(ActByRef<T> proc); void ActUpon<TExtraParam>(ActByRefRef<T, TExtraParam> proc, ref TExtraparam ExtraParam); } public sealed class MutableWrapper<T> : IReadWrite<T> { public T Value; public MutableWrapper(T value) { this.Value = value; } T IReadWriteActUpon<T>.Value {get {return this.Value;} set {this.Value = value;} } public void ActUpon(ActByRef<T> proc) { proc(ref Value); } public void ActUpon<TExtraParam>(ActByRefRef<T, TExtraParam> proc, ref TExtraparam ExtraParam) { proc(ref Value, ref ExtraParam); } }
虽然许多人们本能地包裹领域中的自动性质、领域往往能让更清洁和更有效的代码尤其是当使用价值的类型。在许多情况下,增加的封装一个可以获得通过使用特性的价值可能成本有效和语义,但是,当整个目的,一类是被一个类对象的国家是完全暴露的和可变的,这种封是适得其反。
该接口包括不因为许多用户的一个 MutableWrapper<T>
将要使用的接口,相反,而是因为一个 IReadWriteActUpon<T>
可能是有用的,在各种情况下,其中一些将需要封装和个人有一个实例 MutableWrapper<T>
可能希望通过它的代码,其目的是与数据的封装在一个 IReadWriteActUpon<T>
接口。