zoukankan      html  css  js  c++  java
  • 支持类型过滤的枚举器

        在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需要完成很大规模的遍历工作量,则此时是否使用这种支持类型过滤的遍历器则需要认真判断了。

        以下是演示代码

    using System;

    namespace EnumFilter
    {
        /// 
    <summary>
        /// Class1 的摘要说明。
        /// 
    </summary>
        class Class1
        {
            /// 
    <summary>
            /// 带类型过滤的枚举器对象的测试代码
            /// 
    </summary>
            /// 
    <remarks>编制 袁永福( http://www.xdesigner.cn ) 2007-3-20</remarks>
            [STAThread]
            static void Main(string[] args)
            {
                System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
                doc.LoadXml(@"
    <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>");
            
                // 未使用类型过滤的枚举器
                // 需要在循环中进行类型的转换和判断
                foreach( System.Xml.XmlNode node in doc.DocumentElement.ChildNodes )
                {
                    // 若不加上下行遍历则会发生转换无效错误
                    System.Xml.XmlElement element = node as System.Xml.XmlElement ;
                    if( element != null )
                    {
                        System.Console.WriteLine( element.Name + "  #  " + element.InnerText );
                    }
                }
                System.Console.WriteLine("######################");
                // 使用类型过滤的枚举器
                // 不需要在循环中进行类型的转换和判断
                foreach( System.Xml.XmlElement element in 
                    new TypeFilterEnum( doc.DocumentElement.ChildNodes , typeof( System.Xml.XmlElement )))
                {
                    System.Console.WriteLine( element.Name + "  #  " + element.InnerText );
                }
                System.Console.WriteLine("按回车键退出");
                System.Console.ReadLine();
            }

            /// 
    <summary>
            /// 带类型过滤的枚举器对象
            /// 
    </summary>
            /// 
    <remarks>编制 袁永福( http://www.xdesigner.cn ) 2007-3-20</remarks>
            public class TypeFilterEnum : System.Collections.IEnumerable
            {
                /// 
    <summary>
                /// 初始化对象
                /// 
    </summary>
                /// 
    <param name="e">枚举器</param>
                /// 
    <param name="t">符合的类型</param>
                public TypeFilterEnum( System.Collections.IEnumerator e , System.Type t )
                {
                    this.myEnum = e ;
                    this.myMatchType = t ;
                }

                /// 
    <summary>
                /// 初始化对象
                /// 
    </summary>
                /// 
    <param name="e">枚举器</param>
                /// 
    <param name="t">符合的类型</param>
                public TypeFilterEnum( System.Collections.IEnumerable e , System.Type t )
                {
                    this.myEnum = e.GetEnumerator();
                    this.myMatchType = t ;
                }

                /// 
    <summary>
                /// 返回枚举器对象
                /// 
    </summary>
                /// 
    <returns>枚举器对象</returns>
                public System.Collections.IEnumerator GetEnumerator()
                {
                    MyEnumerator e = new MyEnumerator();
                    e.myEnum = myEnum ;
                    e.myMatchType = myMatchType ;
                    return e ;
                }

                #region 内部代码 **************************************************

                private System.Collections.IEnumerator myEnum = null;
                private System.Type myMatchType = null;

                private class MyEnumerator : System.Collections.IEnumerator
                {
                    internal System.Collections.IEnumerator myEnum = null;
                    internal System.Type myMatchType = null;

                    public void Reset()
                    {
                        myEnum.Reset();
                    }

                    public object Current
                    {
                        get
                        {
                            return myEnum.Current ;
                        }
                    }

                    public bool MoveNext()
                    {
                        while( myEnum.MoveNext())
                        {
                            object o = myEnum.Current ;
                            System.Type t = o.GetType();
                            if( t.Equals( myMatchType ) || t.IsSubclassOf( t ))
                                return true ;
                        }
                        return false;
                    }
                }

                #endregion 
            }//public class TypeFilterEnum : System.Collections.IEnumerable
        }
    }


    袁永福( http://www.xdesigner.cn ) 2007-3-20

  • 相关阅读:
    C语言学习之我见-strcpy()字符串复制函数
    豆邮windows客户端(第三方)开发详解
    项目管理的主要控制因素(转)
    daterangepicker -- bootstrap日期时间范围插件使用分享
    Jacob
    Selenium
    基本套接字总结(@function)
    Python字符串处理NoneType的处理
    机器学习相关会议(转载)
    jboss-AS目录结构了解(资料摘取)
  • 原文地址:https://www.cnblogs.com/xdesigner/p/681126.html
Copyright © 2011-2022 走看看