文章主要目标是让一个java程序员如何迅速适应.net的开发环境,在上一篇已经讲到了开发环境的安装,接下来计划使用两篇博客迅速上手C#,这是第一篇,主要从基础语法和一些简单操作里来体现,通过对比学习的方法,更加深刻的掌握.net的用法和规则,因为楼主即将转向.net开发,所以这里在对比阐述的时候会对c#重点分析。
学习内容来源于:
#C#与Java不同的地方
##整体结构
整体结构的不通风主要体现在层次架构上,java的结构是 项目–包--类(成员变量+成员方法)。而C#则是使用 解决方案–命名空间–类(成员变量+成员函数),接下来从以下几个方面,对整体上的一些不同进行详述。
###程序结构
- 程序的第一行 using System; - using 关键字用于在程序中包含 System 命名空间。 一个程序一般有多个 using 语句。相当于java里的import,引入你需要的包
- 下一行是 namespace 声明。一个 namespace 是一系列的类。HelloWorldApplication 命名空间包含了类 HelloWorld。相当于java里的包,该包下可以有很多类
- 下一行是 class 声明。类 HelloWorld 包含了程序使用的数据和方法声明。类一般包含多个方法。方法定义了类的行为。在这里,HelloWorld 类只有一个 Main 方法。相当于java里的类
- 下一行定义了 Main 方法,是所有 C# 程序的 入口点。Main 方法说明当执行时 类将做什么动作。
###基本语法
语法上的不同,体现在标识符上,而这时唯一的区别就是,java使用的特殊字符是$符,而C#使用的是@符。
###输入输出
- 输出语句
Console.WriteLine("Hello World");
用于向控制台输出语句,类似于java里的System.out.println()。
在输出上java显然更好用一些,直接字符串和参数拼接,而C#需要使用占位符
static void Main(string[] args) { Console.WriteLine("A:{0},a:{1}",65,97); Console.ReadLine(); }
输出顺序与占位符顺序一一对应。
- 输入语句
Console.ReadLine("Hello World");
用于读入用户输入的数值,类似于java里的Scanner,不过比Scanner方便了很多 - Console.ReadKey(); 是针对 VS.NET 用户的。这使得程序会等待一个按键的动作,防止程序从 Visual Studio .NET 启动时屏幕会快速运行并关闭。
###继承和实现的书写
- java里的继承使用extends关键字,实现使用:关键字,而C#统一使用:,在书写规范上C#推荐接口用I开头来区别类和接口的不同。
- java里子类调用父类方法或者实现父类构造方法使用super关键字,而在C#里使用base关键字
##成员变量
成员变量的不同体现在一些常量,不同的变量,C#定义较为繁琐
###常量
C#里的常量使用专用关键字const,而java则使用final。之后还会提到C#定义不可继承方法的时候有专用关键字sealed,而java依旧使用final。
###数据类型
####对于值类型
C#的数据类型里多了很多无符号的值类型,而且多了一个精度更高的 decimal类型。
####对于引用类型
对象类型,字符串类型不用多数,主要的不同就是动态类型,相对于java里的“假”的泛型,我感觉C#的泛型可以说是真泛型了
####对于指针类型
C#官方都说了是不安全方式,我感觉有指针的存在只是为了照顾之前的C和C++的学习者吧。
###类型转换
类型转换上,C#似乎更方便,提供了很全面的方法,显式转换与隐式转换与java大同小异。
###可空类型
该类型在java里并不存在,也不知道这种类型存在的意义
####定义
C# 提供了一个特殊的数据类型,nullable 类型(可空类型),可空类型可以表示其基础值类型正常范围内的值,再加上一个 null 值
using System; namespace CalculatorApplication { class NullablesAtShow { static void Main(string[] args) { int? num1 = null; int? num2 = 45; double? num3 = new double?(); double? num4 = 3.14157; bool? boolval = new bool?(); // 显示值 Console.WriteLine("显示可空类型的值: {0}, {1}, {2}, {3}", num1, num2, num3, num4); Console.WriteLine("一个可空的布尔值: {0}", boolval); Console.ReadLine(); } } }
运行结果
显示可空类型的值: , 45, , 3.14157 一个可空的布尔值:
####合并运算符
Null 合并运算符用于定义可空类型和引用类型的默认值。Null 合并运算符为类型转换定义了一个预设值,以防可空类型的值为 Null。Null 合并运算符把操作数类型隐式转换为另一个可空(或不可空)的值类型的操作数的类型。
如果第一个操作数的值为 null,则运算符返回第二个操作数的值,否则返回第一个操作数的值。下面的实例演示了这点:
using System; namespace CalculatorApplication { class NullablesAtShow { static void Main(string[] args) { double? num1 = null; double? num2 = 3.14157; double num3; num3 = num1 ?? 5.34; Console.WriteLine("num3 的值: {0}", num3); num3 = num2 ?? 5.34; Console.WriteLine("num3 的值: {0}", num3); Console.ReadLine(); } } }
运行结果
num3 的值: 5.34 num3 的值: 3.14157
##成员方法
###访问修饰符
C#提供了5种级别的访问修饰符限定
Private:对象本身在对象内部可以访问;和java一样
Internal:同一个程序集的对象可以访问(对应于java里的default);
Protected:只有该类对象及其子类对象可以访问同一个包中不能访问,这个算是C#比较特有的。
Protected internal:该程序集内的派生类访问,是protected和internal的交集(Protected Internal 访问修饰符允许在本类,派生类或者包含该类的程序集中访问。这也被用于实现继承。);和java里的protected一样
Public:所有对象都可以访问;和java一样
###方法的参数传递
前两种与java的相同,主要区别在于C#多了一种叫做“输出参数”的传递形式。看了很多,理解到,输出参数最重要的作用就是:当需要从一个参数没有指定初始值的方法中返回值时,输出参数特别有用
using System; namespace CalculatorApplication { class NumberManipulator { public void getValues(out int x, out int y ) { Console.WriteLine("请输入第一个值: "); x = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("请输入第二个值: "); y = Convert.ToInt32(Console.ReadLine()); } static void Main(string[] args) { NumberManipulator n = new NumberManipulator(); /* 局部变量定义 */ int a , b; /* 调用函数来获取值 */ n.getValues(out a, out b); Console.WriteLine("在方法调用之后,a 的值: {0}", a); Console.WriteLine("在方法调用之后,b 的值: {0}", b); Console.ReadLine(); } } }
要知道,这里a,b都没有赋初值,但是依然可以使用,这就是输出参数的好处所在。
请输入第一个值: 7 请输入第二个值: 8 在方法调用之后,a 的值: 7 在方法调用之后,b 的值: 8
###重写
几个区别比较大的地方
1,C#里是通过抽象类:虚方法virtual和abstract实现动态多态
####抽象方法
和虚方法类似,只不过没有方法体,和java的类似。
####虚方法
和java里的普通方法类似,但感觉更加规范了,只有需要重写的时候才尽量用virtual方法,其它时候用普通方法。java这块儿就比较模糊了(只要方法名相同,就默认重写)。Java默认的多态,C#要求加上virtual(被继承的方法)和override(继承的方法),而且C#要求不能改变原来的访问修饰符,不像java那样,可以指定更加宽松的访问方式。如果有人利用C#来写程序,必须经常带上virtual和override,还必须照抄原来的访问控制符
using System; class A { public void F() { Console.WriteLine("A.F"); } public virtual void G() { Console.WriteLine("A.G"); Console.ReadKey(); } } class B : A { new public void F() { Console.WriteLine("B.F"); } public override void G() { Console.WriteLine("B.G"); Console.ReadKey(); } } class Test { static void Main() { A a= new B(); a.F(); a.G(); } }
输出结构
A.F //编译看左边,运行看右边,编译看非虚,运行看虚方法 B.G
感觉virtual这个关键字有点儿鸡肋,觉的还是java的方便理解一些
####sealed方法
其实和java里的final差不多,修饰的类不可继承
##一些结论
1,C#和java最大的区别就是java各方面规定比较宽泛,而C#则粒度更加细致,每个方面都规定的特别多详细
2,如果说写代码的体验,肯定是java更好一点儿,不是那么细分,比较好理解,但有些东西规范的比较宽泛,出了错不好排错。如果搭配ide来食用的话,感觉C#+2015食用起来更佳,很多便于团队协作和注释之类的设置,而且2015功能非常强大,但鸡肋的地方就是每次调试都要出框,关了才能修改,比较麻烦,当然也有可能是我现在还没有熟练使用的原因。
#C#额外可使用的地方
##结构体
- 结构可带有方法、字段、索引、属性、运算符方法和事件。
- 结构可定义构造函数,但不能定义析构函数。但是,您不能为结构定义默认的构造函数。默认的构造函数是自动定义的,且不能被改变。
- 与类不同,结构不能继承其他的结构或类。结构不能作为其他结构或类的基础结构。结构可实现一个或多个接口。
- 结构成员不能指定为 abstract、virtual 或 protected。
- 当您使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。与类不同,结构可以不使用 New 操作符即可被实例化。
如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。
不知道该怎么形容结构体,感觉就是为了适用之前的C强行加的。
##析构函数
可能是因为没有JVM如此强大的垃圾回收能力吧,所以使用析构函数来弥补CLR的不足吧,但好像官方也不怎么推荐这个功能。
##预编译与条件指令
1,预处理器指令指导编译器在实际编译开始之前对信息进行预处理。
所有的预处理器指令都是以 # 开始。且在一行上,只有空白字符可以出现在预处理器指令之前。预处理器指令不是语句,所以它们不以分号(;)结束。
2,C# 编译器没有一个单独的预处理器,但是,指令被处理时就像是有一个单独的预处理器一样。在 C# 中,预处理器指令用于在条件编译中起作用。与 C 和 C++ 不同的是,它们不是用来创建宏。一个预处理器指令必须是该行上的唯一指令。
未完待续,现在只是粗浅的认识,之后随着学习的深入会一直更新。。。