博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
支持类型过滤的枚举器
阅读量:7050 次
发布时间:2019-06-28

本文共 3989 字,大约阅读时间需要 13 分钟。

    在VB和C#中,要枚举一个列表中的若干的对象,很容易使用 foreach 结构,抛开性能的话题,foreach 结构简单直观,使用方便。深受广大VB和C#程序员的喜爱。

在C#中,若要实现一个可用于foreach结构的枚举器必须实现 System.Collections.IEnumerable ,然后使用 "foreach( 成员类型 obj in 枚举器变量 )" 的语法结构来使用该枚举器。
    但有些时候,枚举器有时枚举器返回的对象类型可能是变化的,为此我们在foreach循环中需要进行类型转换和判断。

    比如我们对以下XML文档的根节点的子XML元素进行枚举

<
members
>
    文本内容
    
<!--
 注释1 
-->
    
<
aa
>
aaaaaaaaa
</
aa
>
    
<!--
 注释2 
-->
    
<
bb
>
bbbbbbbbbbb
</
bb
>
    文本内容
    
<!--
 注释3 
-->
    
<
cc
>
cccccccc
</
cc
>
    
<!--
 注释4 
-->
    
<!--
 注释5 
-->
    
<!--
 注释6 
-->
    
<
dd
>
eeeeeeeeeee
</
dd
>
    
<!--
 注释7 
-->
    
<
devdoc
>
ffffffffffffff
</
devdoc
>
    
<
devdoc
>
aa
</
devdoc
>
    
<
devdoc
>
文本内容
</
devdoc
>
</
members
>

    很显然,这个XML文档的根节点下有一些不是XML元素的成员。比如文本和注释。此时遍历时需要判断当前节点是否是XML元素类型。为此被迫多些上几行代码,类似的代码写多了那就烦了。

    为了避免这种麻烦,在此提出支持类型过滤的枚举器的概念,这种枚举器是其他枚举器的包装,它能从其他枚举器获得对象,并返回指定类型的当前对象,这样我们使用支持类型过滤的枚举器时,只需要在开始遍历的时候指明所需的对象类型,进行循环遍历的时候就不必再进行类型判断,

使用类型过滤的枚举器,能让我们编写代码时避免一些类型判断的处理,简单可靠,写代码的时候比较舒服。

    此时有人会提出性能问题。在此根据我个人的编程经验,大部分情况下,性能基本大部分是决定于算法,算法设计得好,性能就不会差。各种技术上的包装可能降低性能,但属于细节,无伤大雅。但在少数情况下,算法的具体实现过程就能很大的影响性能,比如若foreach需要完成很大规模的遍历工作量,则此时是否使用这种支持类型过滤的遍历器则需要认真判断了。

    以下是演示代码

None.gif
using System;
None.gif
None.gifnamespace EnumFilter
None.gif{
None.gif    /// 
<
summary
>
None.gif    /// Class1 的摘要说明。
None.gif    /// 
</
summary
>
None.gif    class Class1
None.gif    {
None.gif        /// 
<
summary
>
None.gif        /// 带类型过滤的枚举器对象的测试代码
None.gif        /// 
</
summary
>
None.gif        /// 
<
remarks
>
编制 袁永福( http://www.xdesigner.cn ) 2007-3-20
</
remarks
>
None.gif        [STAThread]
None.gif        static void Main(string[] args)
None.gif        {
None.gif            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
None.gif            doc.LoadXml(@"
None.gif
<
members
>
None.gif    文本内容
None.gif    
<!--
 注释1 
-->
None.gif    
<
aa
>
aaaaaaaaa
</
aa
>
None.gif    
<!--
 注释2 
-->
None.gif    
<
bb
>
bbbbbbbbbbb
</
bb
>
None.gif    文本内容
None.gif    
<!--
 注释3 
-->
None.gif    
<
cc
>
cccccccc
</
cc
>
None.gif    
<!--
 注释4 
-->
None.gif    
<!--
 注释5 
-->
None.gif    
<!--
 注释6 
-->
None.gif    
<
dd
>
eeeeeeeeeee
</
dd
>
None.gif    
<!--
 注释7 
-->
None.gif    
<
devdoc
>
ffffffffffffff
</
devdoc
>
None.gif    
<
devdoc
>
aa
</
devdoc
>
None.gif    
<
devdoc
>
文本内容
</
devdoc
>
None.gif
</
members
>
");
None.gif        
None.gif            // 未使用类型过滤的枚举器
None.gif            // 需要在循环中进行类型的转换和判断
None.gif            foreach( System.Xml.XmlNode node in doc.DocumentElement.ChildNodes )
None.gif            {
None.gif                // 若不加上下行遍历则会发生转换无效错误
None.gif                System.Xml.XmlElement element = node as System.Xml.XmlElement ;
None.gif                if( element != null )
None.gif                {
None.gif                    System.Console.WriteLine( element.Name + "  #  " + element.InnerText );
None.gif                }
None.gif            }
None.gif            System.Console.WriteLine("######################");
None.gif            // 使用类型过滤的枚举器
None.gif            // 不需要在循环中进行类型的转换和判断
None.gif            foreach( System.Xml.XmlElement element in 
None.gif                new TypeFilterEnum( doc.DocumentElement.ChildNodes , typeof( System.Xml.XmlElement )))
None.gif            {
None.gif                System.Console.WriteLine( element.Name + "  #  " + element.InnerText );
None.gif            }
None.gif            System.Console.WriteLine("按回车键退出");
None.gif            System.Console.ReadLine();
None.gif        }
None.gif
None.gif        /// 
<
summary
>
None.gif        /// 带类型过滤的枚举器对象
None.gif        /// 
</
summary
>
None.gif        /// 
<
remarks
>
编制 袁永福( http://www.xdesigner.cn ) 2007-3-20
</
remarks
>
None.gif        public class TypeFilterEnum : System.Collections.IEnumerable
None.gif        {
None.gif            /// 
<
summary
>
None.gif            /// 初始化对象
None.gif            /// 
</
summary
>
None.gif            /// 
<
param 
name
="e"
>
枚举器
</
param
>
None.gif            /// 
<
param 
name
="t"
>
符合的类型
</
param
>
None.gif            public TypeFilterEnum( System.Collections.IEnumerator e , System.Type t )
None.gif            {
None.gif                this.myEnum = e ;
None.gif                this.myMatchType = t ;
None.gif            }
None.gif
None.gif            /// 
<
summary
>
None.gif            /// 初始化对象
None.gif            /// 
</
summary
>
None.gif            /// 
<
param 
name
="e"
>
枚举器
</
param
>
None.gif            /// 
<
param 
name
="t"
>
符合的类型
</
param
>
None.gif            public TypeFilterEnum( System.Collections.IEnumerable e , System.Type t )
None.gif            {
None.gif                this.myEnum = e.GetEnumerator();
None.gif                this.myMatchType = t ;
None.gif            }
None.gif
None.gif            /// 
<
summary
>
None.gif            /// 返回枚举器对象
None.gif            /// 
</
summary
>
None.gif            /// 
<
returns
>
枚举器对象
</
returns
>
None.gif            public System.Collections.IEnumerator GetEnumerator()
None.gif            {
None.gif                MyEnumerator e = new MyEnumerator();
None.gif                e.myEnum = myEnum ;
None.gif                e.myMatchType = myMatchType ;
None.gif                return e ;
None.gif            }
None.gif
None.gif            #region 内部代码 **************************************************
None.gif
None.gif            private System.Collections.IEnumerator myEnum = null;
None.gif            private System.Type myMatchType = null;
None.gif
None.gif            private class MyEnumerator : System.Collections.IEnumerator
None.gif            {
None.gif                internal System.Collections.IEnumerator myEnum = null;
None.gif                internal System.Type myMatchType = null;
None.gif
None.gif                public void Reset()
None.gif                {
None.gif                    myEnum.Reset();
None.gif                }
None.gif
None.gif                public object Current
None.gif                {
None.gif                    get
None.gif                    {
None.gif                        return myEnum.Current ;
None.gif                    }
None.gif                }
None.gif
None.gif                public bool MoveNext()
None.gif                {
None.gif                    while( myEnum.MoveNext())
None.gif                    {
None.gif                        object o = myEnum.Current ;
None.gif                        System.Type t = o.GetType();
None.gif                        if( t.Equals( myMatchType ) || t.IsSubclassOf( t ))
None.gif                            return true ;
None.gif                    }
None.gif                    return false;
None.gif                }
None.gif            }
None.gif
None.gif            #endregion 
None.gif        }//public class TypeFilterEnum : System.Collections.IEnumerable
None.gif    }
None.gif}

袁永福( ) 2007-3-20

 

你可能感兴趣的文章
python学习笔记一
查看>>
Gym 100283F Bakkar In The Army
查看>>
POJ 2947 2947 Widget Factory 高斯消元
查看>>
ExtJS-3.4.0系列:Ext.TabPanel
查看>>
在Eclipse中配置Heritrix-1.14.4版本
查看>>
设计模式笔记:开闭原则(OCP,The Open-Closed Principle)
查看>>
Sql Server系列:键和约束
查看>>
服务器负载感知的URL HASH
查看>>
java xml操作
查看>>
关于Android SDK无法正常下载
查看>>
LVS-DR演示
查看>>
我的友情链接
查看>>
硬件要求
查看>>
基本数据类型
查看>>
我的友情链接
查看>>
C#常见问题总结(二)
查看>>
cmder使用技巧
查看>>
关于dns使用协议的探究
查看>>
我的友情链接
查看>>
我的友情链接
查看>>