我有一个IEnumerable<T>方法,我用来在WebForms页面中找到控件.
该方法是递归的,当返回yield return递归调用的值时,我遇到一些问题,返回我想要的类型.
我的代码如下:
public static IEnumerable<Control>
GetDeepControlsByType<T>(this Control control)
{
foreach(Control c in control.Controls)
{
if (c is T)
{
yield return c;
}
if(c.Controls.Count > 0)
{
yield return c.GetDeepControlsByType<T>();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这当前抛出"无法转换表达式类型"错误.但是IEnumerable<Object>,如果此方法返回类型,则代码构建,但输出中返回错误的类型.
有没有使用yield return同时也使用递归的方法?
我有以下功能来获取卡的验证错误.我的问题涉及处理GetErrors.两种方法都具有相同的返回类型IEnumerable<ErrorInfo>.
private static IEnumerable<ErrorInfo> GetErrors(Card card)
{
var errors = GetMoreErrors(card);
foreach (var e in errors)
yield return e;
// further yield returns for more validation errors
}
Run Code Online (Sandbox Code Playgroud)
是否可以返回所有错误GetMoreErrors而无需通过它们进行枚举?
想一想这可能是一个愚蠢的问题,但我想确保我不会出错.
我使用了很多yield return关键字,但是当我想要添加一个范围时,我发现它缺乏IEnumerable.这是我想做的一个简单示例:
IEnumerable<string> SomeRecursiveMethod()
{
// some code
// ...
yield return SomeRecursiveMethod();
}
Run Code Online (Sandbox Code Playgroud)
当然这会导致错误,可以通过简单的循环来解决.有一个更好的方法吗?一个循环感觉有点笨重.
为什么我们不能在同一方法中同时使用return和yield return?
例如,我们可以在下面使用GetIntegers1和GetIntegers2,但不能使用GetIntegers3.
public IEnumerable<int> GetIntegers1()
{
return new[] { 4, 5, 6 };
}
public IEnumerable<int> GetIntegers2()
{
yield return 1;
yield return 2;
yield return 3;
}
public IEnumerable<int> GetIntegers3()
{
if ( someCondition )
{
return new[] {4, 5, 6}; // compiler error
}
else
{
yield return 1;
yield return 2;
yield return 3;
}
}
Run Code Online (Sandbox Code Playgroud) 我有一个树状的结构.此结构中的每个元素都应该能够返回它所属的所有元素的Enumerable.我们称之为这种方法IEnumerable<Foo> GetAll().所以,如果我们有
A <-- topmost root
/ \
B C
/ \ / \
D E F G
Run Code Online (Sandbox Code Playgroud)
GetAll对元素C返回的调用{C, F, G}(元素的固定顺序很好,但不需要).我想每个人都已经知道了.
目前的实现GetAll看起来像这样:
public IEnumerable<Foo> GetAll ()
{
yield return this;
foreach (Foo foo in MyChildren) {
foreach (Foo f in foo.GetAll ()) {
yield return f;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在早期的实现中,我返回了一个List并添加了child-foos List.AddRange().
我的问题是,是否正确实施了使用产量的版本,或者是否应该改进(特别是在性能方面).或者这只是坏事我应该坚持Lists(或ReadOnlyCollections)而不是?
假设我有以下代码(上下文缩小以保持问题范围有限)
public static IEnumerable<Color> GetThemColors(){
var ids = GetThePrimaryIds();
foreach (int id in ids){
yield return GetColorById(id);
}
ids = GetTheOtherIds();
foreach (int id in ids){
yield return GetOtherColorsById(id);
}
}
Run Code Online (Sandbox Code Playgroud)
我想把它们改写成这样的东西(当然不会编译
public static IEnumerable<Color> GetThemColors(){
GetThePrimaryIds().Select(id=>yield return GetColorById(id));
GetTheOtherIds().Select(id=>yield return GetOtherColorsById(id));
}
Run Code Online (Sandbox Code Playgroud)
关键点在于,在我的第一个片段中,我有两个foreach枚举器屈服,我不知道如何在linq中做什么而不会丢失我的延迟加载功能.
是否存在返回Enumerable中所有项的yield的标准模式?
我经常发现我的一些代码反映了以下模式:
public IEnumerable<object> YieldReturningFunction()
{
...
[logic and various standard yield return]
...
foreach(object obj in methodReturningEnumerable(x,y,z))
{
yield return obj;
}
}
Run Code Online (Sandbox Code Playgroud)
foreach循环的显式用法仅仅是为了向我返回可枚举的代码味道的结果.
显然,我可以放弃使用yield return来增加代码的复杂性,方法是显式构建一个Enumerable并将每个标准yield return的结果添加到它中,并添加methodReturningEnumerable结果的范围.这将是不幸的,因此我希望有一种更好的方法来管理收益率回报模式.
c# ×7
ienumerable ×5
yield ×5
yield-return ×3
.net ×2
generics ×1
lazy-loading ×1
linq ×1
performance ×1
return ×1