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

时间:2022-12-30 21:22:54

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

本文讲解了switch语句可以用来测试string型的对象、多维数组、foreach语句、索引器和Property等内容

1,switch语句可以用来测试string型的对象
这在c,c++,java等其他各主流语言中都是不可以的,唯独c#可以。
例如string a="haha";

复制代码代码如下:
switch(a)
{
    case "dfj":
     ...
    break;
    case "djkfdjkf":
    ....
    break;
    case "haha":
     .....
    break;
    default:
    ....
}

2、多维数组

这也是c#的特色,像java也没有多维数组,只有数组的数组。
c#中不但有数组的数组,也有多维数组。
数组的数组的特点是(拿二维为例),每一行的元素个数可以不同。
比如int [][] c=new int[2][];

复制代码代码如下:
c[0]={3,4,5,6};
c[1]={1};

c#中的多维数组的形式是这样定义

复制代码代码如下:
int [,] c=new int[3,4];

这样的c就是一个三行四列的二维数组。

3,as与is

java中也有类似于is的语法,用于在运行时判断一个对象的类型,叫做instanceof。
c#中就是一个is,判断o是不是一个string:   o is string
as则是一个很窝心的功能,它首先对这个对象进行判断是否是某种类型,如果是就进行类
型转换,如果不是,就返回null。
  如:   o as string

代码如下:

object o = new object();   
Label lb = o as Label;   
if (lb == null)
{
    Response.Write("类型转换失败");
}
else
{     
    Response.Write("类型转换成功");
}

4,foreach语句

java5以后for语句就多了foreach功能,这也许就是因为之前没有,而c#有,使得自己非常嫉妒,所以马上给添上了。

c#中的foreach功能是非常方便的。

例如遍历一个数组

代码如下:
string[] sentences=...;
foreach(string st in sentences)
{
  ....
}
5,索引器和Property

不得不承认,我的偶像Anders实现出来的c#确实非常优秀。
我把索引器和Property归为一类。
都是从Class中读取某种属性,如果知道java的POJO的人肯定知道,java bean的标准形式
就是一堆private属性,然后一个getter,一个setter,这是标准,但实现确实使用的普通成员方法。

c#则更绝,它直接在Class中声明一个单独的field,然后在语法中直接设计了getter和setter的简化写法,这就是我们熟知的Property。
如:

复制代码代码如下:
public class WordCount
{
  private string m_string;
  public string OutFile
  {
     get{...}
     set{...value...}
  }
}

这样真正做到了封闭改动,开放扩展。
然后就是索引器,我觉得java中只有EL才有点做出了类似索引器的功能,这也只是方便了写jsp的人,而且很多厂商居然不在自己的容器中包含EL解析,这不得不让sun很无奈。

索引器就是给几个参数,返回一个属性。
如:

复制代码代码如下:
public int this[string index]
{
  get{...}
  set{..value}
}
public int this[int x,int y]
{
  get{}
  set{..value}
}
6,const和readonly

这点c#让我有点失望,对于非Ref型就是const,对于Ref型就是readonly。
而在java中,一个final就行了。当然对于不可继承的类,c#又有一个关键字sealed,虽然这让程序的含义更明确,但确实也多记了好几个关键字。

7,delegate型别

说实话,这种奇怪的语法还是第一次见到,说跟C++中重载operator()的功能像吧,又不是太像。
总而言之,觉得它实现可能就是记下一堆同类型的函数指针,然后可以依次调用而已。
首先需要声明一个delegate型别,注意是型别而不是对象。
如public delegate void Action();
注意既然是型别,那就跟enum,class是同等的,注意型别能够出现的位置。
然后我们就可以定义这种型别的对象来使用了。

复制代码代码如下:
Action aaa=new Action(...);

这个...代表的是符合这种函数原形的函数名字,注意使用delegate机制来调用,和直接调用函数本质上没有什么不同,就是说,当你调用成员函数的时候,当然你需要有一个对象,而调用静态函数的时候,你可以直接使用类名了。

这种delegate型别对象还有点特殊,它可以使用运算符+=和-=来增加或者减少本对象所代
理的函数集,当然还有更多的方法用来看当前我代理了多少个函数之类的。

复制代码代码如下:
aaa+=new Action(xxx);
aaa+=new Action(ooo);

然后aaa(),意味着顺序调用xxx和ooo。
aaa.GetInvocationList().length可以看到当前代理了多少个函数。
你不用担心代理的普通成员函数的所属对象会被垃圾回收器回收,直到此代理对象不再引用这个函数,当然这个也是坏消息,说不定你都忘了还有某个代理对象代理着要死的对象的函数,让这个对象老不死。

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

本文讲解了internal与protected、private、enum、string的==、传引用等内容

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);

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

本文讲解了在C++中允许从一个case贯穿到另一个case标签、as和is只会检测待转化类型的类型,而不会进行其它操作等内容

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只会检测待转化类型的类型,而不会进行其它操作,所以只有当转化类型是目标类型或者目标类型的子类(当然如果目标类型是接口,并且待转化类型实现了该接口也可以)才能转换成功.
强制转化,会调用系统定义(比如float转化为int类型)或自己定义的转化函数(通过implicit operator定义).

从常规的需求来看,大部分情况下,推荐使用as转换.

但要注意as不能用于value type.因为在转换不成功的时候返回null,而value type不能为
null.这时可以考虑用is.

复制代码代码如下:
object o = 1;
int i = 0;
if(o is int)
i = (int)o;

6.const是编译时常量
readonly是运行时常量
推荐使用static readonly代替const
const变量被硬编码进assembly,有版本问题.
C#只是用sealed替代了fianl,另外C#的派生类在默认情况下不会override基类方法,只有当基类方法用关键字virtual标志,并且子类显式用override标志方法时才会override.这样也有效地解决了版本问题.
7.delegate在本质上就是函数指针.

因为委托还引发了sun和MS的论战.
Anders早在Borland的时候就在Delphi中引入了delegate,后来跑到MS,弄J#的时候又添加进了delegate,Sun很不满意,说他们破坏了Java语言的特性.
到了C#,Anders终于可以名正言顺地添加delegate了.

C#语法相比其它语言比较独特的地方的更多相关文章

  1. php语法基础(相比C语言)

    前言 php的语法跟C语言很类似,相信有一定C的基础的人学起来会非常快. 本篇主要介绍php相比C语言有差异的地方 php代码标记 ASP标记:<% 代码 %> 短标记:<? 代码 ...

  2. Swift相比OC语言有哪些优点

    Swift相比OC语言有哪些优点 1.自动做类型推断 2.可以保证类型使用安全 Swif类型说明符 --Swift增加了Tuple表示元组类型 --Swift增加了Optional表示可选类型 常量一 ...

  3. 为什么和其他语言相比C语言是快速的语言

    初入门的我们经常听见别人说"真正的程序员用C语言编程,C是最快的语言因为它是最靠近及其底层的语言."那么和其他语言相比C语言到底有什么特别的呢? C语言没有什么特别,这就是它快速的 ...

  4. IT兄弟连 Java语法教程 Java语言的其他特性

    Java语言中除了非常重要的跨平台特性外,还有如下几个关键特性: ●  语法简单易学 Java语言的语法简单明了,容易掌握,而且是纯面向对象(OOP)的语言,Java语言的简单性主要体现在以下几个方面 ...

  5. IT兄弟连 Java语法教程 Java语言入门 典面试题

    1.请说明JVM.JRE和JDK是什么?它们有什么关系? JVM是Java虚拟机,Java Virtual Machine的缩写,是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实 ...

  6. IT兄弟连 Java语法教程 Java语言的跨平台特性

    什么是平台 Java是可以跨平台的编程语言,那么首先我们需要知道什么是平台,通常我们把CPU与操作系统的整体称为平台. CPU大家都知道,是计算机的大脑,它既负责思维运算,又负责计算机中各种零部件的命 ...

  7. IT兄弟连 Java语法教程 Java语言背景

    驱使计算机语言革新的因素有两个:程序设计技术的改进和计算环境的改变.Java也不例外.在大量继承C和C++的基础之上,Java还增加了反应当前程序设计技术状态的功能与精华.针对在线环境的蓬勃发展(In ...

  8. VB与C&num;语言部分不用的地方Part1

    1. 数据类型: ① 日期型(Date)      表示日期和时间用两个“#”符号把日期和时间的值括起来,如:#08/20/2001#.#2001-08-20#. ② 变体型(Variant)    ...

  9. 萌新学python

    python python安装 进入官网http://www.python.org/download/ 下载 我下的是3.6.6大家可以根据需要下载(3.x和2.x不兼容请小心) 之后安装就可以了 p ...

随机推荐

  1. Silverlight及WPF中实现自定义BusyIndicator

    在开发Silverlight或者WPF项目时,当我们调用Web服务来加载一些数据时,由于数据量比较大需要较长的时间,需要用户等待,为了给用户友好的提示和避免用户在加载数据过程中进行重复操作,我们通常使 ...

  2. tcp 之失败重传机制

    1.回退N步协议: 滑动窗口模式,每次传送一批的数据,接收到一个就再放进去一个,如果前面一个没有收到回复,后面的就算收到了后面的数据也丢掉 2选择性重传 区别是收到后,缓存.

  3. 使用Fluent配置表关系

    转载MS官方文档:https://msdn.microsoft.com/zh-cn/data/jj591620 Configuring Relationships with the Fluent AP ...

  4. RAC实例 表空间 维护

    先配置一下监听,这样我们就可以从客户端进行连接了. 我这里写了三种连接. 第一种是正常方式,一般都采用这种方式,后面的rac1和rac2 是方便测试.因为如果用第一种方式的话,客户端连哪个实例是随机的 ...

  5. eCos系统CPU负载测量

    原文:http://ecos.sourceware.org/docs-latest/ref/services-cpuload.html 译文:http://blog.csdn.net/zoomdy/a ...

  6. 4Sum -- LeetCode

    原题链接: http://oj.leetcode.com/problems/4sum/  这道题要求跟3Sum差点儿相同,仅仅是需求扩展到四个的数字的和了.我们还是能够依照3Sum中的解法,仅仅是在外 ...

  7. 2015年 10月最新苹果IOS上架App Store商店步骤

    1.1.前期工作 首先你需要有一个苹果的开发者帐号,一个Mac系统. 如果没有帐号可以在打开http://developer.apple.com/申请加入苹果的开发者计划.支付99美元每年,怎么申请网 ...

  8. ASP&period;NET MVC5 高级编程-学习日记-第一章 入门

    1.1 ASP.NET MVC 简介 ASP.NET是一种构建Web应用程序的框架,它将一般的MVC(Model-View-Controller)模式应用于ASP.NET框架. 1.1.1 MVC模式 ...

  9. iOS开发-View中frame和bounds区别

    开发中调整View的时候的经常会遇到frame和bounds,刚开始看的时候不是很清楚,不过看了一下官方文档,frame是确定视图在父视图中的位置,和本身的大小,bounds确定可以确定子视图在当前视 ...

  10. Selenium2&plus;python自动化47-判断弹出框存在&lpar;alert&lowbar;is&lowbar;present&rpar;

    前言 系统弹窗这个是很常见的场景,有时候它不弹出来去操作的话,会抛异常.那么又不知道它啥时候会出来,那么久需要去判断弹窗是否弹出了. 本篇接着Selenium2+python自动化42-判断元素(ex ...