知识大全 C#锐利体验之第八讲 索引器与操作符重载

Posted 操作

篇首语:读书和学习是在别人思想和知识的帮助下,建立起自己的思想和知识。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 C#锐利体验之第八讲 索引器与操作符重载相关的知识,希望对你有一定的参考价值。

C#锐利体验之第八讲 索引器与操作符重载  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  索引器

  索引器(Indexer)是C#引入的一个新型的类成员 它使得对象可以像数组那样被方便 直观的引用 索引器非常类似于我们前面讲到的属性 但索引器可以有参数列表 且只能作用在实例对象上 而不能在类上直接作用 下面是典型的索引器的设计 我们在这里忽略了具体的实现

  class MyClass    public object this [int index]            get                    // 取数据                set                     // 存数据            索引器没有像属性和方法那样的名字 关键字this清楚地表达了索引器引用对象的特征 和属性一样 value关键字在set后的语句块里有参数传递意义 实际上从编译后的IL中间语言代码来看 上面这个索引器被实现为

  class MyClass    public object get_Item(int index)              // 取数据        public void set_Item(int index object value) //存数据    由于我们的索引器在背后被编译成get_Item(int index)和set_Item(int index object value)两个方法 我们甚至不能再在声明实现索引器的类里面声明实现这两个方法 编译器会对这样的行为报错 这样隐含实现的方法同样可以被我们进行调用 继承等操作 和我们自己实现的方法别无二致 通晓C#语言底层的编译实现为我们下面理解C#索引器的行为提供了一个很好的基础

  和方法一样 索引器有 种存取保护级别 和 种继承行为修饰 以及外部索引器 这些行为同方法没有任何差别 这里不再赘述 唯一不同的是索引器不能为静态(static) 这在对象引用的语义下很容易理解 值得注意的是在覆蓋(override)实现索引器时 应该用base[E]来存取父类的索引器

  和属性的实现一样 索引器的数据类型同时为get语句块的返回类型和set语句块中value关键字的类型

  索引器的参数列表也是值得注意的地方 索引 的特征使得索引器必须具备至少一个参数 该参数位于this关键字之后的中括号内 索引器的参数也只能是传值类型 不可以有ref(引用)和out(输出)修饰 参数的数据类型可以是C#中的任何数据类型 C#根据不同的参数签名来进行索引器的多态辨析 中括号内的所有参数在get和set下都可以引用 而value关键字只能在set下作为传递参数

  下面是一个索引器的具体的应用例子 它对我们理解索引器的设计和应用很有帮助

  using System;class BitArrayint[] bits;int length;public BitArray(int length) if (length < ) throw new ArgumentException();bits = new int[((length ) >> ) + ];this length = length;public int Length get return length; public bool this[int index] get if (index < || index >= length) throw new IndexOutOfRangeException();elsereturn (bits[index >> ] & << index) != ;setif (index < || index >= length)throw new IndexOutOfRangeException();else if(value) bits[index >> ] |= << index;elsebits[index >> ] &= ~( << index);class Teststatic void Main() BitArray Bits=new BitArray( );for(int i= ;i< ;i++)Bits[i]=(i% )== ;                        Console Write(Bits[i]+   );编译并运行程序可以得到下面的输出

  True False True False True False True False True False上面的程序通过索引器的使用为用户提供了一个界面友好的bool数组 同时又大大降低了程序的存储空间代价 索引器通常用于对象容器中为其内的对象提供友好的存取界面 这也是为什么C#将方法包装成索引器的原因所在 实际上 我们可以看到索引器在 NET Framework类库中有大量的应用

  操作符重载

  操作符是C#中用于定义类的实例对象间表达式操作的一种成员 和索引器类似 操作符仍然是对方法实现的一种逻辑界面抽象 也就是说在编译成的IL中间语言代码中 操作符仍然是以方法的形式调用的 在类内定义操作符成员又叫操作符重载 C#中的重载操作符共有三种 一元操作符 二元操作符和转换操作符 并不是所有的操作符都可以重载 三种操作符都有相应的可重载操作符集 列于下表

  一元操作符+ ! ~ ++ true false二元操作符+ * / % & | ^ << >> == != > < >= <=转换操作符隐式转换()和显式转换()重载操作符必须是public和static 修饰的 否则会引起编译错误 这在操作符的逻辑语义下是不言而喻的 父类的重载操作符会被子类继承 但这种继承没有覆蓋 隐藏 抽象等行为 不能对重载操作符进行virtual sealed override abstract修饰 操作符的参数必须为传值参数 我们下面来看一个具体的例子

  using System;class Complexdouble  r v;  //r+ v ipublic Complex(double r double v)this r=r;this v=v;public static Complex operator +(Complex a Complex b) return new Complex(a r+b r a v+b v);public static Complex operator (Complex a)return new Complex( a r a v);public static Complex operator ++(Complex a)   double r=a r+ ;  double v=a v+ ;return new Complex(r v);public void Print()Console Write(r+ + +v+ i );class Testpublic static void Main()Complex a=new Complex( );Complex b=new Complex( );Complex c= a;c Print();Complex d=a+b;d Print();a Print();Complex e=a++;a Print();e Print();Complex f=++a;a Print();f Print();编译程序并运行可得到下面的输出

   + i + i + i + i + i + i + i我们这里实现了一个 + 号二元操作符 一个 号一元操作符(取负值) 和一个 ++ 一元操作符 注意这里 我们都没有对传进来的参数作任何改变 这在参数是引用类型的变量是尤其重要 虽然重载操作符的参数只能是传值方式 而我们在返回值时 往往需要 new 一个新的变量 除了true和false操作符 这在重载 ++ 和 操作符时尤其显得重要 也就是说我们做在a++时 我们将丢弃原来的a值 而取代的是新的new出来的值给a! 值得注意的是e=a++或f=++a中e的值或f的值根本与我们重载的操作符返回值没有一点联系!它们的值仅仅是在前置和后置的情况下获得a的旧值或新值而已!前置和后置的行为不难理解

  操作符重载对返回值和参数类型有着相当严格的要求 一元操作符中只有一个参数 操作符 ++ 和 返回值类型和参数类型必须和声明该操作符的类型一样 操作符 + ! ~ 的参数类型必须和声明该操作符的类型一样 返回值类型可以任意 true和false操作符的参数类型必须和声明该操作符的类型一样 而返回值类型必须为bool 而且必须配对出现 也就是说只声明其中一个是不对的 会引起编译错误 参数类型的不同会导致同名的操作符的重载 实际上这是方法重载的表现

  二元操作符参数必须为两个 而且两个必须至少有一个的参数类型为声明该操作符的类型 返回值类型可以任意 有三对操作符也需要必须配对声明出现 它们是 == 和 != > 和 < >= 和 <= 需要注意的是两个参数的类型不同 虽然类型相同但顺序不同都会导致同名的操作符的重载

  转换操作符为不同类型之间提供隐式转换和显式转换 主要用于方法调用 转型表达和赋值操作 转换操作符对其参数类型(被转换类型)和返回值类型(转换类型)也有严格的要求 参数类型和返回值类型不能相同 且两者之间必须至少有一个和定义操作符的类型相同 转换操作符必须定义在被转换类型或转换类型任何其中一个里面 不能对系统定义过的转换操作进行重新定义 两个类型也都不能是object或接口类型 两者之间不能有直接或间接的继承关系 这三种情况系统已经默认转换 我们来看一个例子

  using System;public struct Digitbyte value;public Digit(byte value) if (value < || value > ) throw new ArgumentException();this value = value;public static implicit operator byte(Digit d) return d value;public static explicit operator Digit(byte b) return new Digit(b);上面的例子提供了Digit类型和byte类型之间的隐式转换和显式转换 从Digit到byte的转换为隐式转换 转换过程不会因为丢失任何信息而抛出异常 从byte到Digit的转换为显式转换 转换过程有可能因丢失信息而抛出异常 实际上这也为我们揭示了什么时候声明隐式转换 什么时候声明显示转换的设计原则 不能对同一参数类型同时声明隐式转换和显式转换 隐式转换和显式转换无需配对使用 虽然C#推荐这样做

cha138/Article/program/net/201311/13906

相关参考

知识大全 十天学会ASP.net之第八天

十天学会ASP.net之第八天  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  学习目的初步掌握D

知识大全 详解C#中相等运算符重载可能造成的陷阱

详解C#中相等运算符重载可能造成的陷阱  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  本文将对作

知识大全 C#索引器

C#索引器  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  索引器概述  索引器使得对象可按照与数

知识大全 C# 索引器

C#索引器  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  索引器定义类似于属性但其功能与属性并不

知识大全 实战开发C# 索引器学习笔记

实战开发C#索引器学习笔记  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  简单说来所谓索引器就是

知识大全 php重载数组操作符

  在php中提供了许多接口用于实现一些很特定的功能比如你想把一个对象当作array使用时只需要实现ArrayAccess接口当你想要foreach中能够使用一个对象时只需要实现Iterator接口下

知识大全 实战开发C# 索引器学习笔记[1]

实战开发C#索引器学习笔记[1]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  简单说来所谓索引

知识大全 C# 类中索引器的使用

C#类中索引器的使用  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  索引器(Indexer)是C

知识大全 C# 索引器实战开发学习笔记

C#索引器实战开发学习笔记  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  这是使用C#开发智能手

知识大全 实战开发C# 索引器学习笔记[2]

实战开发C#索引器学习笔记[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  备注: