C# 为什么这个扩展方法不起作用?
我不能做我想做的事。我只想要非国际代表的账户。但是,当我调用ActiveAccounts()时,我得到的不是null,而是一个可枚举的,然后包括null。我做错了什么?请帮忙C# 为什么这个扩展方法不起作用?,c#,.net,.net-3.5,extension-methods,C#,.net,.net 3.5,Extension Methods,我不能做我想做的事。我只想要非国际代表的账户。但是,当我调用ActiveAccounts()时,我得到的不是null,而是一个可枚举的,然后包括null。我做错了什么?请帮忙 public static class AccountExt { public static IEnumerable<Account> ActiveAccounts( this AccountRep rep ) { if( rep == null ) th
public static class AccountExt
{
public static IEnumerable<Account> ActiveAccounts( this AccountRep rep )
{
if( rep == null )
throw new ArgumentNullException();
if( rep.IsInternational )
yield return null;
foreach( var acc in rep.FetchAccounts() )
{
if( acc.IsActive )
yield return acc;
}
}
}
公共静态类AccountExt
{
公共静态IEnumerable ActiveAccounts(此AccountRep)
{
if(rep==null)
抛出新ArgumentNullException();
如果(代表国际)
收益返回空;
foreach(代表FetchAccounts()中的var acc)
{
如果(根据IsActive)
收益率收益率;
}
}
}
嗯,这里有几件事
首先,您不仅有一个扩展方法,还有一个扩展方法迭代器块——这就是您使用收益返回
自动实现IEnumerable
契约时得到的结果
听起来你想要的是
ActiveAccounts()
返回一个nullIEnumerable。你应该用yield break
替换yield return null
。这将返回一个空序列
如果您确实想返回null
而不是IEnumerable
,那么LBushkin的答案就是您想要的答案;但是,更常见的做法是返回空序列,因为它不需要使用者检查返回值。准确地说。我讨厌返回任何类型可枚举的函数返回null。编写代码是很麻烦的。即使使用yield break
,OP也可能希望将方法一分为二,以便立即计算前提条件,而不是迭代枚举数。这可能会导致与实际故障点相去甚远的意外异常。我需要ActiveAccounts()返回null。空枚举不是我需要的,所以会产生中断工作吗?@LBushkin:这是正确的,但我认为前提条件在这里是不必要的。它只检查这个
参数,你真的不需要对此加以防范;不检查只会导致NullReferenceException
,这与您试图调用real(非扩展方法)时完全相同。调用方应该负责不尝试调用空引用上的任何方法-扩展或否。尽管如此,你的回答在技术上是正确的,我确实说了出来@msophie:No,yield break
实际上不会返回null
引用,它将返回一个不带元素的IEnumerable
。我认为在这种情况下返回null
是一种不好的做法,但如果您确实必须返回,则需要LBushkin的答案。
public static class AccountExt
{
// apply preconditions, return null for international reps
public static IEnumerable<Account> ActiveAccounts( this AccountRep rep )
{
if( rep == null )
throw new ArgumentNullException( "rep" );
if( rep.IsInternational )
return null;
// otherwise...
return ActiveAccountsImpl( rep );
}
// private implementation handles returning active accounts
private static IEnumerable<Account> ActiveAccountsImpl( AccountRep rep )
{
foreach( acc in rep.FetchAccounts() )
{
if( acc.IsActive )
yield return acc;
}
}
}
public static IEnumerable<Account> ActiveAccounts( this AccountRep rep )
{
if( rep == null )
throw new ArgumentNullException( "rep" );
if( rep.IsInternational )
return null;
// otherwise, using LINQ to filter the accounts...
return rep.FetchAccounts().Where( acc => acc.IsActive );
}