c#中索引器实验案例及相关算法和类型设计的思考

案例是要实现一个对文档文本进行字符处理,并能筛选分离出文档中的单词,且可以以序列索引来对其中的单词进行访问和修改

完整代码

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 索引2
{
    class Program
    {
        static void Main(string[] args)
        {
            Document mydoc = new Document("Hello,I am a Coder!");
            for (int i = 0; i < mydoc.Words.Count; i++)
                Console.Write(mydoc.Words[i]+" ");
        }
    }

    class Document
    {
        private char[] TextArray;//声明一个char[]数组,用于存储数据
        public WordCollection Words;//声明一个内部WordCollection类型的字段,作为索引属性
        public Document(string initialStr)//构造函数
        {
            TextArray = initialStr.ToCharArray();
            Words = new WordCollection(this);//以当前实例对象初始化改对象的字段属性
        }

        public class WordCollection//用于获得文档中单词集合的类
        {
            readonly Document document;
            internal WordCollection(Document d)
            {
                document = d;
            }
            private bool Getword(char[] text,int begin,int wordcount,out int start,out int length)
            {
                int end = text.Length;
                int count = 0;//初始化符号或空格个数为0
                int inword = -1;//初始化inword为-1,作用是提供单词首字母的指针和空格或数字的判别
                start = length = 0;//初始化单词位置和长度为0
                for (int i = begin; i <= end; ++i)//由外部参数begin开始,遍历字符数组
                {
                    bool isLetter = i < end && Char.IsLetterOrDigit(text[i]);//如果非末尾或为字母或数字,则返回true

                    if (inword >= 0)//判读inword是否重置,可以用于跳过空格或符号
                    {
                        if (!isLetter)//如果为空格或者符号,且前一个字符为单词的末尾
                        {
                            //与索引器的index值(wordcount)进行判断,这里count遇到空格或符号时才会叠加,
                            //而wordcount则表示单词的索引值,则表示未达到指定位置单词是不会返回的,PS:之所以可以比较,是因为索引值是从0开始计算的
                            if (count++ == wordcount)
                            {
                                start = inword;//获取inword为单词的起始值位置
                                length = i - inword;//以当前符号或空格位置减去单词起始位置得到单词长度
                                return true;//返回true并退出
                            }
                            //当遇到空格或符号时,又不是指定的单词索引处,则将inword重置为-1
                            inword = -1;
                        }
                    }
                    else//这里只有为初始状态或当前一个字符为空格或数字才执行
                    {
                        if (isLetter)//如果为字母或者数字
                            inword = i;//如果inword为默认值-1或被重置,且当前为字符,即将字符的索引值赋予inword
                    }
                }
                return false;//指定位置不存在单词,返回false
            }
            public string this[int index]//索引器
            {
                get
                {
                    int start, length;
                    if (Getword(document.TextArray, 0, index, out start, out length))
                    {
                        return new string(document.TextArray, start, length);
                    }
                    else
                        throw new IndexOutOfRangeException();
                }
                set
                {
                    int start, length;
                    if (Getword(document.TextArray, 0, index, out start, out length))
                    {
                        if (length == value.Length)
                        {
                            Array.Copy(value.ToCharArray(), 0, document.TextArray, start, length);
                        }
                        else
                        {
                            char[] newText=new char[document.TextArray.Length+value.Length-length];
                            Array.Copy(document.TextArray, 0, newText, 0, start);
                            Array.Copy(value.ToCharArray(),0,newText,start,value.Length);
                            Array.Copy(document.TextArray, start + length, newText, start + value.Length, document.TextArray.Length - start - length);
                            document.TextArray = newText;
                        }
                    }
                    else
                    {
                        throw new IndexOutOfRangeException();
                    }
                }
            }

            public int Count
            {
                get
                {
                    int count = 0, start = 0, length = 0;
                    while (Getword(document.TextArray, start + length, 0, out start, out length))//利用(start+length)定位到前一个单词之后一个字符所在的位置
                        ++count;//累加所找到的单词的数目
                    return count;
                }
            }

        }

    }
}

 

知识整理

1.索引器的使用适合于具有序列数组性质的数据类型,并要在类型中声明一个可以储存序列数组的字段,例如:

 

 
class Document
    {
        private char[] TextArray;//声明一个char[]数组,用于存储数据
    /*...*/
    }

2.索引器返回的数据类型与本身的数据类型无关,可以自定义返回类型

 class Document
{
        public string this[int index]//索引器,返回string类型数据
            {
                get
                {/*...*/}
            }
}

3.主类中声明的内部类型,可以作为主类的字段或属性来使用

class Document
    {
        private char[] TextArray;//声明一个char[]数组,用于存储数据
        public WordCollection Words;//声明一个内部WordCollection类型的字段,作为索引属性
        public Document(string initialStr)//构造函数
        {
            TextArray = initialStr.ToCharArray();
            Words = new WordCollection(this);//以当前实例对象初始化改对象的字段属性
        }

        public class WordCollection//用于获得文档中单词集合的类
        {
         /*....*/
        }
}

4.利用out进行传址引用的方式传递参数时,可以帮助外部参数初始化,并且可以继续给其他的方法函数继续调用

public string this[int index]//索引器
            {
                get
                {
                    int start, length;//声明2个参数
                    if (Getword(document.TextArray, 0, index, out start, out length))//利用getword判断是否含有单词,并返回start和length的值
                    {
                        return new string(document.TextArray, start, length);//将start和length的值代入string方法中,并返回值
                    }
                    else
                        throw new IndexOutOfRangeException();
                }
          }
posted @ 2012-06-08 12:38  MadKeX  阅读(305)  评论(0编辑  收藏  举报