属性随着产量而丢失
我正在尝试将一些代码从 IList
转换为 IEnumerable
:
[Something(123)]
public IEnumerable<Foo> GetAllFoos()
{
SetupSomething();
DataReader dr = RunSomething();
while (dr.Read())
{
yield return Factory.Create(dr);
}
}
问题是,SetupSomething()
来自基类,并且使用:
Attribute.GetCustomAttribute(
new StackTrace().GetFrame(1).GetMethod(), typeof(Something))
yield
最终创建 MoveNext()
、MoveNext()
调用 SetupSomething()
和 MoveNext()
没有 [Something(123)]
属性。
我无法更改基类,因此看来我被迫继续使用 IList
或手动实现 IEnumerable
(并将属性添加到 MoveNext()< /代码>)。
在这种情况下还有其他方法可以让收益发挥作用吗?
There is some code that I'm trying to convert from IList
to IEnumerable
:
[Something(123)]
public IEnumerable<Foo> GetAllFoos()
{
SetupSomething();
DataReader dr = RunSomething();
while (dr.Read())
{
yield return Factory.Create(dr);
}
}
The problem is, SetupSomething()
comes from the base class and uses:
Attribute.GetCustomAttribute(
new StackTrace().GetFrame(1).GetMethod(), typeof(Something))
yield
ends up creating MoveNext()
, MoveNext()
calls SetupSomething()
, and MoveNext()
does not have the [Something(123)]
attribute.
I can't change the base class, so it appears I am forced to stay with IList
or implement IEnumerable
manually (and add the attribute to MoveNext()
).
Is there any other way to make yield work in this scenario?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果您需要堆栈帧功能,则不能使用迭代器(yield)。正如您所发现的,这会将您的方法重写为实现
IEnumerable
的自定义类。但是,您可以轻松地将其修改为:
您失去了迭代器的延迟执行,但它会正常工作。
You can't use iterators (yield) if you require the stack frame functionality. As you've discovered, this rewrites your method into a custom class that implements
IEnumerable<T>
.However, you can easily just rework this to:
You lose the deferred execution of the iterator, but it will work properly.
您可以将该方法包装在另一个执行所有必需预处理的方法中:
You can wrap the method in another method that does all required preprocessing:
你能像这样分解你的方法吗?
Could you split your method up, like this?
从您的描述来看,问题似乎在于 SetupSomething 仅查看堆栈跟踪上的直接调用者。如果它进一步向上查找(调用者的调用者),它将找到您的 GetAllFocus 调用和所需的属性。
我不记得了,但如果yield创建一个MoveNext()实现只是因为你的类还没有实现它,也许你可以实现你自己的MoveNext,把属性放在它上面,然后yield就会找到并使用你的 MoveNext()?只是一个疯狂的猜测。
From your description, it sounds like the problem is that SetupSomething is only looking at the immediate caller on the stack trace. If it looked a little further up (caller's caller) it would find your GetAllFocus call and the desired attribute.
I don't recall off the top of my head, but if yield is creating a MoveNext() implementation only because your class doesn't already implement it, perhaps you can implement your own MoveNext, put the attribute on it, and yield will find and use your MoveNext()? Just a wild guess.
我可能遗漏了一些东西,但我无法理解这里使用属性的意义。你不妨这样写:
也快了一大截。更安全的是,当 JIT 编译器内联 SetupSomething() 时,您就完蛋了。
I'm probably missing something, but I can't make sense of using an attribute here. You might as well have written it like this:
A whole heckofalot faster too. And safer, you're dead in the water when the JIT compiler inlines SetupSomething().