C#语法相比其它语言比较独特的地方(二)

之前有个兄弟给我的卷一re了帖子,我当时没有g,m,直到他把它删掉才后悔莫及,人生最痛苦的事情莫过于此。。。。。。

好,即便如此,我们还是满怀希望的向前奔去。接着写卷二。

还要提一下,上次最后说到的delegate,在我了解了它的实现和用途以及看到我的偶像的一些访问记录后,我对它有了很深的理解,并且在事件处理机制上,我更偏向于我偶像这边,有兄弟说MFC是switch,java是listener,其实java这些listener在processEvent里面还不是一个个switch然后调用,都是switch,那switch就不能说是特点了,最大的特点还是是否直接使用函数指针来进行响应这点上。往下又说信号处理,以前的8259A发生中断查中断向量表进行到头来也是地址转移阿,这也没特点,到后来调用都是地址转移,而速度的差别就在于在同样不可避免具有某些相同层次实现的情况下,机制不同架构不同造成的效率差别,这就完全取决于实力了。

1,internal与protected,private

C#默认的,当定义一个class的时候,如果你没有加任何访问修饰子,那么该class的访问权限即为internal,当然你可以显式制定为internal。internal是什么呢?internal就是说在当前工程中,都可访问,不管你自己用了几个名称空间,都无所谓。

但是在定义一个class中的成员变量的时候,假如你什么都不写,那么这个成员变量默认的权限就是private。如果你要这个成员在当前工程中也可以被访问,则必须使用internal关键字来显式的修饰它。

另外,c#里面的protected访问权限仍然和以前的c++中是一致的含义,表示只有继承者才有访问权限。即便是同一个工程,同一个名称空间中的别的类,都别想看到这个protected成员,颇为严格的一个访问限制。

internal和protected基本控制访问是在不同的领域,他们两个是可以同时用来修饰一个对象的。比如

代码如下:

class PPP
    {
        internal protected static int c=3;

}

没有交集,也不会互斥。

这跟java是截然不同的,其实我本可以完全不提java,但由于我自己的背景和一个通盘概括,我还是把java的拿出来与c#进行类比。毕竟本文标题是“特别之处”,当然,这里我也不知道你会认为是c#特别,还是java特别了。

java中没有完全相同于这个internel似的访问控制,它有一种独特的package访问控制。不管是类还是类的成员,如果你不写访问修饰,那么它就是package访问级别的,package访问级别的含义是在本package中都可以访问。java中没有那种类似internal的“在本工程”或者本“jar”中可以访问的这种级别,只有package级别。
而java中的protected也是比c#中的protected要宽容得多,java中的protected的含义其实等价于c#中的protected并上java中的package。有人打了这么一个比方,说大宅门,有很多资源都是protected的,这些资源不但可以造福四邻(同在一个package中),还可以给自己的儿子阿,孙子阿(儿子孙子通过继承得到资源)即便他们远走他乡。

2,enum

我们学过C,C中定义enum中的元素符号的时候,这个符号不能够与当前作用域中的其他符号相同,并且,所有这些enum中的符号可以直接拿来当常数使用,就好像是#define了一个整形常量一般。特别是当不制定enum类型标记的时候,那简直就是个#define。

C++中几乎与C中相同,不同的是,当定义一个这种enum对象的时候,不用
写  enum 类型标记 对象;
而只用写  类型标记 对象; 即可。

就好像以前必须写 struct 类型标记 对象;

而在c++中就可以只用写  类型标记 对象;  一样但是不管是在c#或者是java中,首先它们都不可以省略类型标记。其次,不用确保必须不同于同个作用域的其他标记符。再者,不可以直接把enum中的元素符号直接拿过来当常量。起码也要写,类型标记.元素符号 才行。
比如

代码如下:

enum XXX{A,B,C,D}
....
Console.writeLine(XXX.A);

但是C#中又有其特别之处,它保留了部分c的enum才有的功能。那就是可以用运算符+、-来对enum对象进行运算,这是java绝对做不到了,而且还可以转换回int型别。比如

代码如下:

enum weekdays{sunday,monday.....saturday}
for(weekdays wd=weekdays.sunday;wd<=weekdays.saturday;wd++)
   ...
(int)weekdays.sunday   //结果是0

也可以赋值

代码如下:

enum open_modes{
  intput=1,output,append,
  last_input_mode=input,last_output_mode=output
}

如果你觉得默认实现是int型太耗,可以用byte型

代码如下:

enum weekdays:byte{
....
}

3.string的==
我们都知道Equals方法可以给人覆盖用来判断两个对象是否是同值,而==作用于两个对象只能比较两个对象的ref是否相等。

我们在java中比较两个字符串是否相等用的是"hello".equals(aaa);
但是在c#中,string对象的==运算已经被强行重写,它就是表示equals,
这就是说,在c#中,实现字符串值比较的话,只需要写成"hello"==aaa就行了,
这样设计的目的是为了更直观。

4.传引用

在java中有个非常经典的问题,这个问题的到访真是让我习以为常。
那就是字符串处理函数的问题。
在java或者c#中,有人

代码如下:

void processString(String a)
{
    a=a+"asdfjsdf";
}

或者说是数字交换问题

代码如下:

void processInt(int a,int b)
{
  int temp=a;
   a=b;b=temp;
}

前者还有说的,后者则是连c的基础都没打好了,后者的话建议去补习C。
前者我来说一下,不管是java中还是c#中,string对象都是immutable的,即一经产生,就无法改变,那么+运算符做了什么呢?它将生成一个新的string对象,然后把+两边的string的内容都填进来。

也就是说a+"asdfdjkf"这个东西是一个全新的东西,如果写成a+="asdfj"或者a=a+"sdfjk"那么原来的a和这个"asdjf"就可以被GC了。

再说java和c#中的对象型别,java和c#中所有的对象型别都是ref型别,也就是说。

代码如下:

String a;

这么一句话,只是定义了一个ref,它基本上不占用任何资源,也没有生成任何真正的对象,它只是一个ref。

String a="dkfjsdf";的时候,在受控堆上生成一个对象"dkfjsdf",然后返回这个对象的ref给a。

我们再看刚才那个字符串处理,a只是一个类似局部变量的形式参数,你将a的ref设为一个新值,然后函数返回,形式参数a没了,原来的实际参数啥变化都没有。

但是你说,我就是要这样处理,这么办呢?在java中,就没法这样处理String,不过StringBuffer之类的倒是可以,因为我们虽然无法改变实际参数的ref值,但是却可以通过相同值ref更改对象内部成员,对于immutable的我们没办法,但对于mutable的我们就可以捏了。

而在c#中,非常恭喜你可以得逞了。就像我们刚才设想的那样去处理string是可以的,不过要这样做。

代码如下:

void processString(ref string a)
{
  a+="sdjkf";
}

加上了ref,就取消了形式参数的产生和压退栈,就好像c++中的string &了,相当于是直接将实际参数交给你了。
这样我们对它为所欲为都是可以的,这样我们的processString就得逞了。
不过在填实际参数的时候,需要写成这样

代码如下:

string h="haha";
processString(ref h);
Console.WriteLine(h);

我们就可以看到h被改变了。

5,out参数

out参数就好像直接通过c#语言实现了com接口定义中的out的语义一样。
就是输出参数,我们知道不管是windows api还是com,函数返回值通常用来处理异常的,而真正处理的结果是通过输出参数带回的,输出参数实现有很多种方式,比如传地址,传引用,当然com中从来不用c++中诡异的那个&引用。

out参数跟我们之前提到的ref参数唯一不同的就在于,ref参数在填到实参之前,必须初始化,而out参数无此要求,它就是用来带回结果的,你可以定义一个未初始化的局部变量,然后用out 变量名的写法填进去,调用完毕,值就放在这个变量里了。

比如我们改改刚才的processString来说明out参数用法

代码如下:

void processString( out string a)
{
   a="xxx";
}

string a;
processString(out a);
Console.WriteLine(a);

(0)

相关推荐

  • C#语法相比其它语言比较独特的地方(三)

    1.在C++中允许从一个case贯穿到另一个case标签 比如: 复制代码 代码如下: int a =1; switch(a) {   case 1:      some statements;   case 2;      other statements;      break; } 第一个case和第二个case之间可以没有break 而在C#中这个break不能省略. 3.as和is只会检测待转化类型的类型,而不会进行其它操作,所以只有当转化类型是目标类型或者目标类型的子类(当然如果目标

  • C#语法相比其它语言比较独特的地方(一)

    由于c#是由设计.net本身的人设计出来的,所以c#才是.net上最一流的语言. 实际上,已经有一百多万行c#代码用于实现.Net class framework. 要发挥出.net平台全部的效能,只有c#才是首选. 1,switch语句可以用来测试string型的对象 这在c,c++,java等其他各主流语言中都是不可以的,唯独c#可以. 例如string a="haha"; 复制代码 代码如下: switch(a) {     case "dfj":     

  • C#语法相比其它语言比较独特的地方(二)

    之前有个兄弟给我的卷一re了帖子,我当时没有g,m,直到他把它删掉才后悔莫及,人生最痛苦的事情莫过于此...... 好,即便如此,我们还是满怀希望的向前奔去.接着写卷二. 还要提一下,上次最后说到的delegate,在我了解了它的实现和用途以及看到我的偶像的一些访问记录后,我对它有了很深的理解,并且在事件处理机制上,我更偏向于我偶像这边,有兄弟说MFC是switch,java是listener,其实java这些listener在processEvent里面还不是一个个switch然后调用,都是s

  • 详解C语言用malloc函数申请二维动态数组的实例

    详解C语言用malloc函数申请二维动态数组的实例 C语言在程序运行中动态的申请及释放内存十分方便,一维数组的申请及释放比较简单. Sample one #include <stdio.h> int main() { char * p=(char *)malloc(sizeof(char)*5);//申请包含5个字符型的数组 free(p); return 0; } 是否申请二维动态内存也如此简单呢?答案是否定的.申请二维数组有一下几种方法 Sample two /* 申请一个5行3列的字符型

  • 易语言是在VB6上二次开发或二次封装吗

    有朋友曾猜测易语言是在VB6基础上二次开发或二次封装的产品. 我在这里提几个思路可用于协助否定该猜测. VB6编译的程序在Windows 95系统内运行需要VB6运行库(MSVBVM60.dll直到Win98才被操作系统内置),而易语言编译的程序不需要该运行库. 易语言支持通过置入代码向目标编译程序输出x86机器码,而VB6没有类似的功能. 易语言支持静态编译EXE和DLL(非普通的打包然后在运行时释放DLL),而VB6没有类似的功能. 易语言支持直接使用C/C++的静态库(.lib/.obj)

  • C语言实现24位彩色图像二值化

    本文实例为大家分享了C语言实现24位彩色图像二值化的具体代码,供大家参考,具体内容如下 // huiduhua.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<stdio.h> #include<windows.h> int _tmain(int argc, _TCHAR* argv[]) { BITMAPFILEHEADER bfhead; BITMAPINFOHEADER bihead; RGBQUA

  • C语言算法练习之求二维数组最值问题

    目录 一.问题描述 二.算法实例编译环境 三.算法实例实现过程 3.1.包含头文件 3.2.定义宏和声明数组 3.3.声明相关变量 3.4.输入数组(方阵)的阶 3.5.输出 “输入的数组” 3.6.计算每行最大数据中的 最小的那一个数字 3.7.计算每行最小数据中的 最大的那一个数字 四.经典算法实例程序 4.1.main.h文件 4.2.main.c文件 五.总结 一.问题描述 求二维数组最大最小值 问题的描述 如下几点所示 1.在n 行 n 列的二维整数数组中,按以下要求选出两个数. 2.

  • RedHatLinux7.1中语言化完全攻略(二)

    1.设置中文locale RedHat的locale切换很简单:进入Linux窗口界面,执行locale_config会弹出一个选择本地语言窗口,选择"Chinese(CN.GB2312) zh_CN.GB2312"来设置locale为"简体中文",如果你想试用一下"繁体中文",也可以选择"Chinese(TW.Big5) zh_TW.Big5". 2.中文locale应用 打开一个控制台,运行date命令.怎么看到的是一行乱

  • Go语言七篇入门教程二程序结构与数据类型

    目录 1. 程序结构 1.1 名称 1.2 声明 1.3 注释 1.4 单双引号 1.5 输出 2. 数据类型 2.1 整型 2.2 浮点型 2.3 复数 2.4 布尔型 2.5 字符串 2.6 常量 2.7 数组 2.8 切片 2.9 map 2.10 结构体 2.11 JSON 3. 流程控制 3.1 条件语句 3.2 选择语句 3.3 循环语句 如何学习Go 1. 程序结构 1.1 名称 如果一个实体名称在函数中声明,它只在函数局部有效.如果声明在函数外,它将对包里面的所有源文件可见. 实

  • 易语言实现截图或右键二维码识别的代码

    DLL命令表 .版本 2 .DLL命令 DecodePictureFile, 整数型, "PsyQrDcd", "DecodePictureFile" .参数 strFilePath, 文本型 .DLL命令 DecodePictureFileRect, 整数型, "PsyQrDcd", "DecodePictureFileRect" .参数 strFilePath, 文本型 .参数 lngLeftX, 整数型 .参数 lngT

随机推荐