C# yield在WCF中的错误用法(一)

 更新时间:2015年04月10日 11:09:01   投稿:junjie  
这篇文章主要介绍了C# yield在WCF中的错误使用(一),本文讲解的内容据说是99%的开发人员都有可能犯的错误,需要的朋友可以参考下

在定义API的时候,对于一些返回集合对象的方法,很多人喜欢将返回类型定义成IEnumerable<T>,这本没有什么问题。这里要说的是另一个问题:对于返回类型为IEnumerable<T>的方法来说,我们可以使用yield return的方式来输出返回集合的元素。但是如果我们不了解yield 关键字背后的实现机制,很有可能造成很大的问题。

这是一个WCF相关的问题,我想99%的人都有可能会犯这样的错误——即使你对yield了解得非常透彻。闲话少说,我们通过一个简单的实例来说明这个问题。我们定义了如下一个IDemoService接口作为服务契约,唯一的方法GetItems返回一个类型为IEnumerable<string>对象,并且具有唯一字符串参数category。

复制代码 代码如下:

  [ServiceContract]
  public interface IDemoService
  {
      [OperationContract]
      IEnumerable<string> GetItems(string category);
  }

下面是实现了该契约接口的DemoService的实现:GetItems方法返回一个包含3个字符串的集合,但是在返回之前我们需要对参数实施验证。如果category参数提供的字符串为Null或者是空字符串,抛出一个FaultException异常并提示“Invalid Category”,这样客户端在输入不合法参数的情况下可以得到错误消息。这样的编程方式再正常不过了,不是吗?
复制代码 代码如下:

public class DemoService : IDemoService
{
    public IEnumerable<string> GetItems(string categoty)
    {
        if (string.IsNullOrEmpty(categoty))
        {
            throw new FaultException("Invalid category");
        }
        yield return "Foo";
        yield return "Bar";
        yield return "Baz";
    }
}

可是正常并不意味着正确,客户端其实根本无法得到服务端提供给它的错误消息,如下所示的是客户端调用服务时指定一个空字符串参数情况下得到的错误。一个CommunicationException异常被抛出来,得到的错误消息为“An error occurred while receiving the HTTP response to http://127.0.0.1:3721/demoservice. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.”

这貌似和我们预期的效果不一样,我们希望的是客户端抛出一个FaultException,并提示“Invalid category”。这实际上就是因为“yield”在作祟,不相信的话可以将定义在DemoService的GetItems方法替换成如下的定义,即直接返回一个string[]对像。

复制代码 代码如下:

public class DemoService : IDemoService
{
    public IEnumerable<string> GetItems(string categoty)
    {
        if (string.IsNullOrEmpty(categoty))
        {
            throw new FaultException("Invalid category");
        }
        return new string[] { "Foo", "Bar", "Baz" };
    }
}

再次运行我们的程序,这回可以得到我们期望的结果了。

有兴趣的朋友可以思考一下为什么两种貌似等效的方式为何会出现完全不同的结果,具体原因请看[下篇]。

相关文章

  • C# Record构造函数的行为更改详解

    C# Record构造函数的行为更改详解

    C# 9 中的record类型是仅具有只读属性的轻量级、不可变数据类型(或轻量级类),下面这篇文章主要给大家介绍了关于C# Record构造函数的行为更改的相关资料,需要的朋友可以参考下
    2021-08-08
  • C#常用数据结构之数组Array

    C#常用数据结构之数组Array

    这篇文章介绍了C#常用数据结构之数组Array,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • C# XML操作类分享

    C# XML操作类分享

    这篇文章主要分享了C# XML操作类的实例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • Unity 实现给物体替换材质球

    Unity 实现给物体替换材质球

    这篇文章主要介绍了Unity 实现给物体替换材质球的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • C#中DataSet,DataTable,DataView的区别与用法

    C#中DataSet,DataTable,DataView的区别与用法

    这篇文章介绍了C#中DataSet,DataTable,DataView的区别与用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • C#使用itextsharp生成PDF文件的实现代码

    C#使用itextsharp生成PDF文件的实现代码

    以下是对在C#中使用itextsharp生成PDF文件的实现代码进行了详细分析介绍,需要的朋友可以过来参考下
    2013-07-07
  • C#实现将应用程序设置为开机启动的方法

    C#实现将应用程序设置为开机启动的方法

    这篇文章主要介绍了C#实现将应用程序设置为开机启动的方法,涉及C#针对注册表的写入技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-09-09
  • Unity性能优化Shader函数ShaderUtil.GetShaderGlobalKeywords用法示例

    Unity性能优化Shader函数ShaderUtil.GetShaderGlobalKeywords用法示例

    这篇文章主要为大家介绍了Unity性能优化Shader函数ShaderUtil.GetShaderGlobalKeywords用法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • 浅谈C#中的Async和Await的用法详解

    浅谈C#中的Async和Await的用法详解

    这篇文章主要介绍了浅谈C#中的Async和Await的用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Unity3D开发教程:愤怒的小鸟

    Unity3D开发教程:愤怒的小鸟

    这篇文章详细的讲解了如何从0开发出一个Unity3D的小游戏愤怒的小鸟,本文包含大量的图片与文字描述,也含有大量的源代码,可以让你快速入手,希望本篇文章对你有所帮助
    2021-06-06

最新评论