c# - 为什么这种扩展方法不起作用?

标签 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 )
            throw new ArgumentNullException();
        if( rep.IsInternational )
            yield return null;

        foreach( var acc in rep.FetchAccounts() )
        {
            if( acc.IsActive )
                yield return acc;
        }
    }
}

最佳答案

好吧,这里发生了几件事。

首先,您不仅有一个扩展方法,您还有一个扩展方法迭代器 block - 这就是您使用 yield return 时得到的结果自动执行 IEnumerable<>契约(Contract)。

听起来您想要发生的是 ActiveAccounts()返回空 IEnumerable<Account> .实际发生的情况是,对于国际代表,您将返回 null 作为 IEnumerable 的第一个元素。我怀疑你可能 试过使用return null那里有一个编译器错误,例如:

Error: Cannot return a value from an iterator. Use the yield return statement to return a value, or yield break to end the iteration.

如果您的目的是让枚举为空,那么您需要的是 yield break而不是 yield return null .通常,返回一个空序列实际上是一个更好的主意,因为它允许调用者避免检查返回值。它还可以更好地使用 LINQ 等技术,这些技术使用组合来组装复杂的查询。

第二个问题是 if( rep == null )调用 ActiveAccounts() 时不评估前提条件,而是当您开始枚举该调用的结果时。这可能不是您想要的 - 我想您希望立即评估先决条件。

解决这两个问题的方法是使用两阶段实现:

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;
       }
   }
}

如果您愿意使用 LINQ,可以避免 Impl函数版本:

   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 );
   }

您可以了解有关迭代器如何阻塞 here 的更多信息.

关于c# - 为什么这种扩展方法不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2248794/

相关文章:

c# - 用C#学习单一职责原则

c# - LinqToXml 还是 Xml?

java - 在java中将RAW图像转换为jpg

.net - 免费的 NHibernate 辅助工具?

c# - export 'XYZ.IMessageCenterBL (ContractName="XYZ.IMessageCenterBL")' is not assignable to type ' System.Web.Mvc.JsonResult'

时间:2019-03-17 标签:c#语言: Error while trying to save parameters to MySql DB using C#

c# - UWP 创建 VPN 连接

.net - Winforms 中的 VB.Net UserControl 关闭事件

c# - 如何实现具有多个应用程序实例的进度条?

c# - 缺少 Dictionary<TKey,TValue>.KeyCollection 扩展方法 .NET 3.5 (C#)