第一句子大全,网罗天下好句子,好文章尽在本站!

深入体验C#锐利技巧(八)

时间:2024-02-02

C#锐利体验八是一本专为C#编程语言初学者和进阶者准备的实用教程,全面介绍了C#语言的基础知识和高级应用技巧。本书囊括了C#程序设计的核心概念、语法规则,以及C#在实际开发中的...

友情提示:本文共有 4653 个字,阅读大概需要 10 分钟。

《C#锐利体验(八)》是一本专为C#编程语言初学者和进阶者准备的实用教程,全面介绍了C#语言的基础知识和高级应用技巧。本书囊括了C#程序设计的核心概念、语法规则,以及C#在实际开发中的常用技术和最佳实践。读者可以通过本书系统地学习C#的各种特性和用法,提高自己的编程能力,并且掌握更多开发技巧。《C#锐利体验(八)》还以丰富的案例和实例帮助读者深入理解和掌握C#编程,让读者在实际工作和项目中能够运用自如,提高工作效率。无论是初学者还是有一定经验的开发者,都能从本书中获得实用的经验和知识。

下面小编要跟大家分享C#锐利体验(八),简单的过程中其实暗藏玄机,还是要细心学习,喜欢还请记得收藏哦!

索引器

索引器(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#索引器的行为提供了一个很好的基础。

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

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

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

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

using System;class BitArray{int[] bits;int length;public BitArray(int length){if (length 0)throw new ArgumentException();bits = new int[((length - 1) 5) + 1]; = length;}public int Length{get { return length; }}public bool this[int index]{get{if (index 0 || index = length)throw new IndexOutOfRangeException();elsereturn (bits[index 5] & 1 index) != 0;}set{if (index 0 || index = length)throw new IndexOutOfRangeException();else if(value)bits[index 5] |= 1 index;elsebits[index 5] &= ~(1 index);}}}class Test{static void Main(){BitArray Bits=new BitArray(10);for(int i=0;i10;i++)Bits[i]=(i%2)==0;(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 Complex{double 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+1;double v=a.v+1;return new Complex(r, v);}public void Print(){(r+" + "+v+"i");}}class Test{public static void Main(){Complex a=new Complex(3,4);Complex b=new Complex(5,6);Complex c=-a;() d=a+b;()() e=a++;()() f=++a;()();}}

编译程序并运行可得到下面的输出:

-3 + -4i 8 + 10i 3 + 4i 4 + 5i 3 + 4i 5 + 6i 5 + 6i

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

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

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

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

using System;public struct Digit{byte value;public Digit(byte value){if (value 0 || value 9)throw new ArgumentException(); = value;}public static implicit operator byte(Digit d){return } static explicit operator Digit(byte b){return new Digit(b);}}

上面的例子提供了Digit类型和byte类型之间的隐式转换和显式转换。从Digit到byte的转换为隐式转换,转换过程不会因为丢失任何信息而抛出异常。从byte到Digit的转换为显式转换,转换过程有可能因丢失信息而抛出异常。实际上这也为我们揭示了什么时候声明隐式转换,什么时候声明显示转换的设计原则。不能对同一参数类型同时声明隐式转换和显式转换。隐式转换和显式转换无需配对使用--虽然C#推荐这样做。

实际上可以看到,对于属性,索引器和操作符这些C#提供给我们的界面操作,都是方法的某种形式的逻辑抽象包装,它旨在为我们定义的类型的用户提供一个友好易用的界面--我们完全可以通过方法来实现它们实现的功能。理解了这样的设计初衷,我们才会恰当,正确地用好这些操作,而不致导致滥用和错用。

本文如果对你有帮助,请点赞收藏《深入体验C#锐利技巧(八)》,同时在此感谢原作者。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。
显示评论内容(5)
  1. 小楫夜泊2024-02-02 07:46小楫夜泊[江苏省网友]116.193.182.213
    @急速绚空这篇内容让我对C#有了更深刻的认识,感谢作者的分享。
    顶0踩0
  2. 急速绚空2024-02-02 07:43急速绚空[陕西省网友]103.228.13.72
    文章结构清晰,通俗易懂,让我对C#的一些技巧豁然开朗。
    顶0踩0
  3. 卧听夜雨2024-02-02 07:40卧听夜雨[北京市网友]157.255.103.2
    @BurydesireC#锐利技巧(八)的内容很丰富,学到了不少新知识。
    顶8踩0
  4. Burydesire2024-02-02 07:37Burydesire[上海市网友]203.18.75.20
    看完后觉得对C#的掌握又加深了一层,写得很详细,易于理解。
    顶9踩0
  5. 黎明前的黑2024-02-02 07:35黎明前的黑[天津市网友]103.59.115.148
    这篇文章很实用,让我对C#的一些技巧有了更深的理解。
    顶7踩0
相关阅读
[小雨学编程之C#] 19.2 流程控制语句 if else

[小雨学编程之C#] 19.2 流程控制语句 if else

那么内容看到这里,我们是否有种似曾相识的感觉?大家是否想起了之前我们学过的三元运算符!表达式?成立:不成立;那么,我们的这段代码可以简单修改一

2022-12-30 #经典句子

[小雨学编程之C#] 19.3 流程控制语句 if else if

[小雨学编程之C#] 19.3 流程控制语句 if else if

虽然我们生活中,这种非此即彼的判断条件比比皆是,比如一个数字要么大于0,要么小于0,一个人要么已经过生日了,要么还没过生日:但是细心的小伙伴会发

2023-06-25 #经典句子

[小雨学编程之C#] 19.5 从流程控制语句聊聊编程思维

[小雨学编程之C#] 19.5 从流程控制语句聊聊编程思维

我们本节内容同时用if else if 和 switch来完成这个练习

2023-06-24 #经典句子

[小雨学编程之C#] 19.8 流程控制语句 for

[小雨学编程之C#] 19.8 流程控制语句 for

我们的新知识点就是循环语句for,它的语法是:for循环初值;判断条件;循环增量{每次循环需要做的事情}我们直接用一个例子说明语法,输出0~9这10个数字:

2022-12-30 #经典句子

[小雨学编程之C#] 19.7 流程控制语句 do while

[小雨学编程之C#] 19.7 流程控制语句 do while

在学习新的内容之前,我们简单回顾一下上节内容中的一个例子,模拟报价:在这个例子中,我们首先创造了一个无限循环条件whiletrue,然后在这个无限循环中

2022-12-30 #经典句子

[小雨学编程之C#] 19.6 流程控制语句 while

[小雨学编程之C#] 19.6 流程控制语句 while

模拟用户登陆,错误输入账户、密码满3次,程序结束

2022-12-30 #经典句子

C#深入浅出:拓展你的数据类型知识

C#深入浅出:拓展你的数据类型知识

本书从基础数据类型如整型、浮点型到更复杂的数据类型如数组、集合等进行了详细介绍,旨在帮助读者更好地理解和运用C#中的数据类型

2024-01-31 #大杂绘

有课│刘纪宏:语言三大技巧:重音 停顿和语调

有课│刘纪宏:语言三大技巧:重音 停顿和语调

这三个技巧,是有声语言表达中经常要遇到的

2013-04-11 #经典句子

小学语文造句技巧大全 帮孩子解决造句难题 附经典例句 超实用

小学语文造句技巧大全 帮孩子解决造句难题 附经典例句 超实用

家长跟孩子相互配合,共同为孩子打好一个基础,这样基础打好了,孩子语文学起来也就不会吃力,也就会慢慢的爱上语文的学习

2023-05-15 #经典句子