C#成魔之路<4>C#面向对象高级技术(2)

1、迭代器

使用foreach语句遍历数组或者集合时,该语句可以逐一列举出集合或者数组中的元素,这正是迭代器的功能体现。

迭代器概念:
迭代器是可以返回相同类型的值的有序序列的一段代码,可以用作方法、运算符或者get访问器的代码体。迭代器代码使用yield return语句依次返回每个元素,yield break语句将终止迭代。可以在类中实现多个迭代器,每个迭代器都必须像任何类成员一样有唯一的名称,并且可以在foreach语句中被客户端代码调用。迭代器的返回类型必须是IEnumerable或IEnumerator中的任意一种。

迭代器运用:
创建迭代器最常用的方法是对IEnumerator接口实现GetEnumerator方法,下面通过实例进行演示如何使用迭代器。

namespace IEnumeratorTest1
{
    public class Banks : IEnumerable<string>
    {
        string[] strArray = { "工商银行", "建设银行", "中国银行", "农业银行" };
        public IEnumerator<string> GetEnumerator()
        {
            for (int i = 0; i < strArray.Length; i++)
            {
                yield return strArray[i];
            }
        }
    }

    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Banks bank = new Banks();
            foreach (string str in bank)
            {
                richTextBox1.Text += str + "\n";
            }
        }
    }
}

//上述程序不能在VS2012中运行,需要进行再次修改。

2、分部类
在编写类的时候为了实现一些特殊的需求,比如:无限创建源文件既可将代码添加到类中,尽可能的提高开发人员之间的合作效率。C#提供了内部类的概念。

(1)分部类概念
分部类的出现是的程序的结构更加合理。代码的组织更加紧密。分部类将类、结构或者接口的定义拆分到两个或者多个源文件中。每个源文件包含类定义的一部分。编译应用程序时,编译器会把所有部分组合起来,这样的类称为分部类。分部类主要应用在以下几个方面:
I.当项目比较庞大的时候,使用分部类可以拆分一个类至几个文件中。这样的处理可以使得不同的开发人员同时进行工作,避免了效率低下。
II.使用自动生成的源时,无需重新创建源文件就可以代码添加到类中。VS在创建Windows窗体和Web服务包装代码等时,都使用这个方法。

(2)分部类的使用

定义分部类时需要使用partial关键字,分部类的每个部分都必须包含一个partial 关键字,并且其声明必须和其他部分位于同一个命名空间。

示例程序:简单的四则运算计算器:

namespace partialTest
{

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.Items.Add("加法");
            comboBox1.Items.Add("减法");
            comboBox1.Items.Add("乘法");
            comboBox1.Items.Add("除法");
            comboBox1.SelectedIndex = 0;
            comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                account at = new account();
                int M = int.Parse(textBox1.Text.Trim());
                int N = int.Parse(textBox2.Text.Trim());
                string str = comboBox1.Text;
                switch(str)
                {
                    case "加法":
                        textBox3.Text=at.addition(M,N).ToString(); break;
                    case "减法":
                         textBox3.Text=at.subtraction(M,N).ToString(); break;
                    case "乘法":
                         textBox3.Text=at.multiplication(M,N).ToString(); break;
                    case "除法":
                         textBox3.Text=at.divition(M,N).ToString(); break;

                }

            }
            catch (Exception ex)
            { }
        }
    }
}

利用分部类所做的account类:

 partial class account
    {
        public int addition(int a, int b)
        {
            return a + b;
        }
    }

    partial class account
    {
        public int multiplication(int a, int b)
        {
            return a * b;
        }
    }
    partial class account
    {
        public int subtraction(int a, int b)
        {
            return a - b;
        }
    }
    partial class account
    {
        public int divition(int a, int b)
        {
            return a / b;
        }
    }

3、泛型
泛型是用来处理算法的、数据结构的一种编程方法。泛型的目标是采用广泛使用和可交互性的形式来表示算法和数据结构,以使他们能够直接用于软件构造。泛型类、结构、接口、委托和方法可以根据他们存储和操作的数据类型来进行参数化。泛型能在编译的时候,提供强大的类型检查,减少数据类型之间的显示转换、装箱操作和运行时的类型检查。泛型类和泛型方法同时具备可重用性、类型安全和效率高等特性,这是非泛型类和非泛型方法无法具备的。泛型通常用在集合和在集合上运行的方法中。
泛型主要是提高了代码的重用性。

(1)类型参数T
泛型的类型参数T可以看做是一个占位符。其不是一种类型,仅仅代表了某种可能的类型。在定义泛型时T出现的位置可以在使用时用任何类型来代替。类型参数T的命名准则如下:
使用描述性名称命名泛型类型参数,除非单个字母名称完全可以让人了解它表示的含义,而描述性名称不会有更多的含义。

public interface IStudent<TStudent>

使用T作为描述性类型参数名的前缀。

public interface IStudent<T>
{
T sex {get;}
}

(2)泛型接口
声明泛型接口的时候,和声明一般接口的唯一区别是增加了一个< T>。一般来说,声明泛型接口和声明非泛型接口遵循相同的规则。泛型类型声明所实现的接口必须对所有可能的构造类型都保持唯一:否则无法确定该为某些构造类型调用哪个方法。
泛型接口的声明形式:

interface 接口名<T>
{
//接口体
}

示例程序:

namespace T_Test
{
    public interface ITest<T>
    {
        T CreateIObject();
    }
    //实现上面泛型接口的泛型类
    //派生约束whereT:TI(T要继承自TI)
    //构造函数约束whereT:new() (T可以被实例化)
    public class Test<T, TI> : ITest<TI> where T : TI, new()
    {
        public TI CreateIObject()//创建一个公共方法
        { 
        return new T();//返回T类型的对象
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            ITest<System.ComponentModel.IListSource> itest=new
            Test<System.Data.DataTable,System.ComponentModel.IListSource>();
            Console.WriteLine("数据类型: \n"+itest.CreateIObject().GetType().ToString());
            Console.ReadLine();
        }
    }
}

(3)泛型方法
泛型方法是在声明中包括了类型参数T 的方法。泛型方法可以在类、结构或者接口证明中声明,这些类、结构或者接口本身可以是泛型或者非泛型。如果在泛型类型声明中声明泛型方法,则方法体可以同时引用该方法的类型参数T和包含该方法的声明的类型参数T。
泛型方法可以使用多类型参数进行重载。
泛型方法的声明形式:

修饰符 Void 方法名 <类型参数 T>
{
//方法体
}

示例程序 :通过定义一个泛型方法,查找数组中的某个数字的位置。

namespace T_Test1
{
    public class FindHelper
    {
        public static int Find<T> (T[] items, T item)
        {
            for (int i = 0; i < items.Length; i++)
            {
                if (items[i].Equals(item))
                {
                    return i;
                }
            }
            return -1;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            int i = FindHelper.Find<int>(new int[]{1,2,3,4,5,6,7,8,9},9);
            Console.WriteLine("9 在数组当中的位置是:"+i.ToString());
            Console.ReadLine();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值