首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 冲浪宝典-> 联络聊天
从模拟字符串型的枚举说起 [c#]_c#应用
作者:网友供稿 点击:0
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 

1. 有字符串型的枚举吗?

UK 在《关于枚举的种种》中提到这样一个问题:

枚举的成员类型都是数值型的,如果想做一个字符型的枚举有什么办法?

    enum colors : string{
        red=#ff0000,
       
    }
在展开讨论之前,我认为有必要搞清楚另一个问题,上面代码中的 #ff0000 不是字符而是字符串,应改成 "#ff0000",于是,UK 的问题也顺利成章地改成“想做一个字符串型的枚举有什么办法”了。

很坦白地说,.NET 并不支持这样的字符串型枚举。另外,也不是所有的数值类型都能作为枚举的底层类型,枚举的底层类型只能是整数类型,这意味着某天你想定义一个底层类型为 double 的枚举,你将会收到编译器的警告信。

UK 的代码确实提出了这样一种需求,colors 就像一个枚举,但其成员的值是一个字符串,于是,我们很容易产生这样一个疑问:是否能够模拟出这样一个枚举呢?

 

2. 有办法模拟出来吗?

在写任何代码之前,让我们首先思考一下,假如真有这样一个 Color 类,我们会怎样使用它?以下是我想到的两个用法:

1// Code #01
2
3Color c1 = Color.Red;
4string s1 = (string)c1;
5Debug.Assert(s1 == "#FF0000");
6
7Color c2 = (Color)"#00FF00";
8Debug.Assert(c2 == Color.Green);
首先,枚举是通过其成员而不是构造函数来初始化的,正如上面代码的第三行。于是,我们应该把构造函数设为私有,同时模拟一些枚举成员并暴露出来:

// Code #02

public class Color
{
    private Color(string value)
    {
        m_Value = value;
    }

    private string m_Value;

    public static readonly Color Red = new Color("#FF0000");
    public static readonly Color Green = new Color("#00FF00");
    public static readonly Color Blue = new Color("#0000FF");
}
这样,Code #01 的第三行就可以工作了。值得提醒的是,Red、Green 和 Blue 等成员的值都是不变的,为了不让客户代码修改它们的值,我把它们设成 readonly(注意:它们不可以设为 const,你知道为什么吗?)。另外,它们应该属于 Color 类而不是某个实例的,于是把它们设成 static。

接着,Code #01 的第四行说明了 Color 的实例可以强制转换成字符串,这可以通过重载转换运算符做到:

// Code #03

public static explicit operator string(Color value)
{
    return value.m_Value;
}
与 Code #01 的第四行对应的是 Code #01 的第七行,它说明了字符串可以强制转换成 Color 实例,这也是通过重载转换运算符做到的:

// Code #04

public static explicit operator Color(string value)
{
    switch (value)
    {
        case "#FF0000":
            return Red;
        case "#00FF00":
            return Green;
        case "#0000FF":
            return Blue;
        default:
            throw new InvalidCastException();
    }
}
很明显,并不是所有的字符串都可以转换成 Color 实例,所以,当客户代码试图把一个含有非预期值的字符串转换成 Color 实例时就应该抛出 InvalidCastException 了。

诚然,有些人会对 Code #04 很反感,因为它里面有一个 switch!当我们使用枚举时,我们并不只是用它来进行一些值的转换或者获取其字面值,我们更希望用它来标识不同的情况或者类别,并根据枚举实例的值来判断属于哪一情况或类别。换句话说,当我们决定使用枚举时,我们就注定与条件语句结下不解之缘了。

最后,这里给出 Color 的完整代码:

// Code #05

Color#region Color

public class Color
{
    private Color(string value)
    {
        m_Value = value;
    }

    public static explicit operator Color(string value)
    {
        switch (value)
        {
            case "#FF0000":
                return Red;
            case "#00FF00":
                return Green;
            case "#0000FF":
                return Blue;
            default:
                throw new InvalidCastException();
        }
    }

    public static explicit operator string(Color value)
    {
        return value.m_Value;
    }

    public override string ToString()
    {
        return m_Value;
    }

    public static readonly Color Red = new Color("#FF0000");
    public static readonly Color Green = new Color("#00FF00");
    public static readonly Color Blue = new Color("#0000FF");

    private string m_Value;
}

#endregion
或许有人会提出这样一个问题:我们经常会对枚举进行判等运算,但为什么 Code #05 中既没有重载 Object.Equals 方法,也没有提供 == 和 != 运算符呢?细心观察 Color 的代码,你会发现获取 Color 的实例只有两种途径:通过静态只读字段和通过强制转换运算符,但无论你是如何得到 Color 的实例,这些实例最终都是源自 Color 内部的静态只读字段。换言之,通过这两种途径分别获得的两个 Color 实例其实是同一个实例。

 

3. 模拟方案有什么问题吗?

我相信,Color 在一定程度上能够满足 UK 的需求了,但是,我认为 Color 并不一定能用到实际的应用中去。回顾 Code #05,Color 既是一个枚举也是一个数据载体。说它是枚举,是因为我们刻意把它模拟成枚举;说它是一个数据载体,是因为我们并不仅仅以枚举的方式来用它,我们更需要的是成员背后所代表的值。这意味着 Color 承担的责任多于一个,违反了单一责任原则(SRP)。

我怀疑,UK 之所以对 Color 有这样的期望,或多或少是受到了《关于枚举的种种》中枚举成员的值那部分内容的影响,尤其是“为什么需要手动指定枚举成员的值?”这个问题的答案。如果真是这样,我必须就该文产生误导在此向你道歉。现实的情况往往不会像该文的 Code #13 那样简单,不但同一类型的顾客(例如白金会员)所能享受到的折扣随时会发生变化,而且同一的商品在不同的时期(例如促销期)的折扣也有可能不同,于是顾客最终所能享受到的折扣可能是一个经过复杂运算的综合折扣。任何对变化因素的硬编码都会导致系统的僵化!我建议在阅读该文这部分内容时应以研究枚举的这方面特性为目的。

另一方面,Color 作为一个数据载体,它确实弱得可怜。目前它仅包含 R、G、B 三个通道的数据,如果我想加入 alpha 通道的数据呢?这会对它的代码产生多大的冲击?如果我希望它能分别为我提取 A、R、G、B 四个通道的数据呢?如果我希望实现 RGB 和 CMYK 之间的数据转换呢?我相信这些问题已经足够让你头痛一周了,但当你知道人的肉眼能够识别的颜色约有一千六百万种,而这些颜色都可以通过 RGB 值来描述并作为显示器输出的依据,你的鼠标会不会马上指向浏览器右上角的交叉呢?

很明显,这里所给出的 Color 是经不起时间的考验的,于是我不禁在想,.NET Framework 究竟如何表达 Color 呢?它又是如何满足这些让人苦闷的需求呢?

 

4. .NET Framework 又如何表达 Color 呢?

在 .NET Framework 中,和这里所提到的需求相关的东西有3个:Color 结构、KnownColor 枚举和 ColorTranslator 类,它们都位于 System.Drawing 命名空间中。

首先说说 KnownColor 枚举,它的成员可以分成两类:一类是有名字的颜色,与它们对应的 RGB 值是不变的,如 Indigo 是靛蓝;另一类是外观项目的颜色,与它们对应的 RGB 值会随着用户的设置而改变,如 InfoText 是工具提示文本的颜色。

其次是 Color 结构了,它有很多静态属性,这些属性都是获取与 KnownColor 枚举中第一类成员对应的 Color 实例。它还提供 FromKnownColor 和 ToKnownColor 方法用于实现它的实例和 KnownColor 枚举之间的转换。当然,由于它是一个数据载体,它包含了 A、R、G、B 四个通道的数据,对它的实例的判等就相当于对这些数据进行判等,于是它也重载了 == 和 != 运算符。

说了这么多,好像还没有提到如何从 Color 实例得到 HTML 颜色值,好吧,现在是时候让 ColorTranslator 类登场了。该类提供 ToHtml 和 FromHtml 方法用于实现 Color 实例和 HTML 颜色值的字符串之间的转换。

这三个东西的责任都很明晰,当你需要判断某个地方用的是否某种颜色时,没有必要去比较它们的 A、R、G、B 四个通道的数据,你真正需要的只是一种快而准的标识对比,KnownColor 枚举恰恰就能满足这方面的要求;当你需要操作某种颜色的数据时,你其实并不希望操作一个字符串,Color 结构能让你轻易提取所需的数据;当你在颜色数据和 HTML 颜色值的字符串之间进行转换时,你其实并不太需要一个枚举来做标识。然而,你也有可能结合它们三个一起使用,下面给出一个例子作为本文的收尾:

// Code #06

string desktopColorValue = ColorTranslator.ToHtml(Color.FromKnownColor(KnownColor.Desktop));

http://www.cnblogs.com/allenlooplee/archive/2006/09/06/496874.html


文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·Java Unicode转义字符的小小研究-JSP教程,Java技巧及代码
·实现VB与EXCEL的无缝连接-.NET教程,VB.Net语言
·在ASP.NET里通过URL传递参数得到乱码的解决方法-ASP教程,ASP应用
·实例讲解:Java中的SOAP技术-JSP教程,Java技巧及代码
·Session过期问题-ASP教程,ASP应用
·设计模式笔记-抽象工厂模式-.NET教程,评论及其它
·JSP标准标记库促进了网页的开发-JSP教程,Jsp/Servlet
·在Remoting Server上取得Remoting Client的IP地址-ASP教程,ASP应用
·使用JSP标记库校验用户输入-JSP教程,Jsp/Servlet
·c#中DataGrid的数据新增编辑删除操作代码-.NET教程,数据库应用
最新文章
·xp也能享受vista readyboost闪存加速_windows xp
·c# 3.0新特性系列:隐含类型var_c#教程
·如此做google广告,月赚10万美金不成问题_网赚技巧
·王通:个人博客的赚钱之道_网赚技巧
·这一年来风风雨雨-再访中客宋陈磊_站长访谈
·个人网站的定位推广和赚钱-访中国建站站长_站长访谈
·祥瑞网方文春:从800元到6000万元_站长访谈
·行业类、专业性成功网站给个人站长的启示_站长访谈
·网站推广 新招老招齐用上_站长心得
·widnows vista工具栏添加快速启动tabletpc图标_windows vista
相关主题
西部数码虚拟主机

友情链接
CNNIC 西部数码
万网 自助建站
虚拟主机 asp空间
域名注册 域名
域名申请 主页空间
论坛空间 网站空间
国际域名 虚拟空间
空间租用 DDOS防火墙
成都主机托管 四川主机托管
主机租用 服务器租用
网站目录 自助建站
虚拟主机 网址大全
软件下载
自助链接
虚拟主机资讯 特价虚拟主机
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
发表评论 打印  刷新     关闭