浏览模式: 标准 | 列表

因为C#中没有提供 Switch on Type 的功能,因此要判断类型通常会用一长串的if else,当然这种写法的问题是不够高效,且不够美观。因此 C# 中对常见类型提供了一组枚举值,也就是 TypeCode(这个枚举类型在.NET for Windows App Store 中居然被取消了,大概是因为DBNull这个类型本身也被取消了,这个值没有对应的类型了,干脆连TypeCode就一起取消了)。可以使用 Type.GetTypeCode 方法来得到类型对应的枚举值,之后对得到的枚举值进行switch操作。但需要注意这里有一组特殊的类型,那就是枚举类型,它的返回值是该枚举类型对应的数字类型,而不是Object类型。

因此如果你想区分枚举类型和数字类型的话,记住不要直接用这个方法,至少要先用 IsEnum 来判断一下。否则你可能会错把枚举了类型当成数字类型进行处理。

1月
03

C# 中 is 和数组的问题

在C#中,我们可以很方便的在object对象上使用is运算符来快速的判断对象的类型,is运算符还具有在子类对象上判断是否属于某个父类或者接口的能力,与之等价的判断是,使用GetType方法获得类型后,使用父类或接口上的IsAssignableFrom方法来判断。后者速度比使用 is 运算符要慢很多。所以通常我们在存在对象和已知要判断的类型时优先使用is运算符。

但是is运算符在判断数组类型时却有一个bug,当然这个bug也许是设计问题,但是它确实可能跟我们期望的行为不一致。

这个bug可以这样描述,当一个整数数组对象(byte[], sbyte[], short[], ushort[], int[], uint[], long[], unlong[]这八种)被赋值给一个object对象时,在这个object对象上使用is方法判断时,在等位长整数类型上判断的结果总为True,与类型是否有符号无关。例如:

C#代码
 
  1. int[] a = new int[] { -3, -2, -1, 0, 1, 2, 3 };  
  2. Console.WriteLine(a is int[]);  
  3. Console.WriteLine(a is uint[]);  
  4. object o = a;  
  5. Console.WriteLine(o is int[]);  
  6. Console.WriteLine(o is uint[]);  
的输出结果为:

True
False
True
True

前三个输出是我们期望的,但是最后一个输出的True却是出乎意料的。

这里如果把 int[] a 换成 uint[] a 也是一样,例如:

C#代码
 
  1. uint[] a2 = new uint[] { 0, 1, 2, 3 };  
  2. Console.WriteLine(a2 is int[]);  
  3. Console.WriteLine(a2 is uint[]);  
  4. o = a2;  
  5. Console.WriteLine(o is int[]);  
  6. Console.WriteLine(o is uint[]);  
的输出结果是:

False
True
True
True

第三个输出结果True是我们意料之外的。

同样byte[]和sbyte[]也存在这种关系,short[]和ushort[],long[]和ulong[]之间同样也存在这种关系。

所以使用is在这几种数组的object对象上做判断时,一定要注意这个问题,否则很容易掉进这个陷阱中去。

在 .NET Framework 3.5 beta 时,微软曾引入了一个新的包 System.Numerics,其中包含了大整数类,不过可惜在后来的接近发布时,这个包又移除了。现在 .NET Framework 4.0 又重新将它请了回来。而且这次的正式版本中不会再次移除了。这对 .NET 开发者算是一个好事,但如果只有使用 .NET Framework 4.0 的用户才能享受到这个包,还是不太完美,毕竟现在大多数 .NET 开发还停留在 2.0 或 3.5 的阶段。

我们最近新推出的 PHPRPC 的商业版 Hprose 最显著的一个特点就是多语言互通,让各个版本的 .NET 程序之间无障碍互通更是小菜一碟。但如果只有 .NET 4.0 中有 BigInteger,就无法将其传给 .NET 的早期版本,怎么谈得上无障碍互通呢?为了解决这个问题,我们将 System.Numerics 移植到了 .NET 4.0 之前的所有版本上,现在不但 .NET Framework 1.0、1.1、2.0、3.5 可以使用 System.Numerics 的所有类了,连 .NET Compact Framework 1.0、2.0、3.5,SilverLight 2.0、3.0、4.0,Mono 1.0、Mono 2.0 也都可以使用了。

虽然我们的商业版Hprose本身不是免费的,但是这个移植的 System.Numerics.dll 我们是免费开放的。你不需要支付任何费用,就可以将它用于您的任何程序当中。是不是很爽?哈哈,那还等什么,还不赶快下载试试。

下载地址:System.Numerics.dll

» 阅读全文

昨天晚上终于把 Silverlight 2 的开发工具下载完了,装好之后打算测试一下 PHPRPC for .NET 客户端是否可以在 Silverlight 2 上运行,因为原来的 PHPRPC for JavaScript 可以很好的在 Silverlight 1 上运行,本以为 PHPRPC for .NET 也应该很顺利的在 Silverlight 2 上运行,可是测试之后才发现完全不是那么回事。通过查看 MSDN,才知道 Silverlight 2 支持的 .NET 框架也是一个精简的框架,而这个精简的框架不但不同于 .NET Framework,而且也不同于 .NET Compact Framework. 这里主要说一下常用的一些不同之处:

Silverlight 2 将 System.Collections 名空间中的大部分容器类都拿掉了,比如 ArrayList、Hashtable 等这些常用的容器现在都不可以再用了。取而代之的是 System.Collections.Generic 名空间中的那些泛型容器类。看来 Silverlight 2 是打算要强制用户使用泛型类了。

Silverlight 2 中的 System.Net.HttpWebRequest 只支持异步操作,而不再支持同步操作了,看来是害怕用户使用同步操作将浏览器卡死,就直接干掉同步操作了。不过 Silverlight 2 是支持多线程的,在单独的线程中做同步调用应该是不会卡死浏览器的。所以感觉 Silverlight 2 将 System.Net.HttpWebRequest 的同步操作干掉是多此一举。

Silverlight 2 中的 System.Net.HttpWebRequest 和 System.Net.HttpWebResponse 支持的属性明显减少了。尤其是 System.Net.HttpWebResponse, 连 Headers 属性都没有了。所以根本就没有办法操作服务器端返回的特殊头信息了。我想这应该是为安全考虑才这样做的吧。另外,也没法操作 Cookie,但愿这两个类能够自动处理 Cookie 吧,如果不支持 Cookie 的话,那可就太糟糕了。

Silverlight 2 支持 System.Reflection.Emit,而 .NET Compact Framework 不支持。这是比较好的一点,因为有了 System.Reflection.Emit 之后,就可以动态创建类型,这对于实现远程调用来说就方便很多了。

当然还有许多其他的一些不同点,但我暂时还没接触到,这里就不说了。

没办法,如果想让 PHPRPC for .NET 支持 Silverlight 2 的话,看来只能改代码了。自己实现
ArrayList、Hashtable 这两个容器,还要增加异步调用的支持,这些改动还真不小呢。

» 阅读全文

这个版本目前实现了对各种基元类型、一维数组、多维数组、交错数组、ArrayList、Hashtable、和其它可序列化对象的序列化。实现了 PHP 5 中的 Serializable 接口的支持。实现了 PHP 中的 __sleep 和 __wakeup 魔术方法的支持。实现了对所有标示(N、b、i、d、s、a、O、R、r、U、C)的反序列化,在对标示 a 反序列化时,可以根据下标和值来自动判断是 ArrayList 还是 Hashtable。并且在反序列化时可以强制指定反序列化的类型。

该类是静态类,无需也不能被实例化。除了包含了 Serialize 和 UnSerialize 方法以外,还增加了一个 ChangeType 方法,用来进行反序列化后的类型转换,该方法比 Convert.ChangeType 方法的转换的能力更强。

» 阅读全文