总体了解C#

毕业设计——第二章 系统总体设计(1) 第一章     系统总体设计如前所述,“排水GIS地理信息系统”属于专业系统,与公众系统相比而言,公众GIS系统用户友好性是关键,而专业系统注重是专业只是的系统体现。专业系统设计时,必须考虑使用者的心理。比如:(1)操作简单。虽说是专业软件,但是主要使用对象是非计算机专业的人员操作,所以必须考虑软件的操作简洁、方便,并具有一定的趣味性,使用户对该系统有信心和兴趣;(2)在GIS原理和功能表达上 阅读详情

总体了解C#(1 C#和Java)

A Comparative Overview of C#中文版

 

作者:Ben Albahari

公司:Genamics

日期:2000年7月31日初版,2000年8月10日修订。

感谢以下人士支持和反馈(按字母先后顺序):Don Box、 C.R. Manning、 Joe Nalewabau、 John Osborn、 Thomas Rhode & Daryl Richter。

译者:荣耀

 

1.       下面是C#和Java共有的特性列表,目的都是为了改进C++。这些特性虽非本文重点,但了解它们之间的相似之处还是很重要的。

编译为机器独立、语言独立的代码,运行在受控执行环境里;

采用垃圾收集机制,同时摒弃了指针(C#中,指针被限制在标为unsafe的代码内使用);

强有力的反射能力;

没有头文件,所有的代码都在包或组合体里,不存在类声明的循环依赖问题;

所有的类都派生自object,且必须用new关键字分配在堆上;

【译注:Java中为Object;C#中为object,相当于.NET的System.Object】

当进入标为锁定/同步代码时,通过在对象上加锁来支持多线程;

【译注:例如Java中可对方法施以synchronized关键字,在C#中可使用Monitor类、Mutex类、lock语句等等】

接口支持—多继承接口,单继承实现;

 

内部类;

类继承时无需指定访问级别;

【译注:在C++中,你可以这么做:class cls2: private cls1{};等等】

没有全局函数或常量,一切都必须属于类;

数组和字符串都保存长度记数并具边界检查能力;

永远使用“.”操作符,不再有“->”、“::”操作符;

null和boolean/bool是关键字;

【译注:Java中为boolean、C#中为bool,相当于System.Boolean】

所有的值在使用前必须被初始化;

if语句不能使用整型数为判别条件;

try语句块后可以跟finally从句。

【译注:标准C++不可以,但Visual C++对SEH做了扩展,可以用__try和__finally】

 

2.       属性

对于Delphi和Visual Basic的用户来说,属性是个熟悉的概念。使用属性的目的是将获取器/设置器[译注:原文为getter/setter]的概念正式化,这是一个被广泛使用的模式,尤其是在RAD(快速应用开发)工具里。

以下是你可能在Java或C++里写的典型代码:

foo.setSize (getSize () + 1);

label.getFont().setBold (true);

 

同样代码在C#里可能会变成:

foo.size++;

label.font.bold = true;

 

C#代码对于使用foo和label的用户来说更直观、更可读。在实现属性方面,差不多同样简单:

//Java/C++:

public int getSize()

{

return size;

}

public void setSize (int value)

{

size = value;

}

//C#:

public int Size

{

get {return size;}

set {size = value;}

}

 

特别是对于可读写的属性,C#提供了一个处理此概念的更清爽的方式。在C#中,get和set方法是内在的,而在Java和C++里则需人为维护。

C#的处理方式有诸多优点。它鼓励程序员按照属性的方式去思考——把这个属性标为可读写的和只读的哪个更自然?或者根本不应该为属性?如果你想改变你的属性的名称,你只要检查一处就可以了(我曾看到过中间隔了几百行代码的获取器和设置器【译注:此处是指C++(Java)里对同一个数据成员/字段(一般来说是)的获取器和设置器】)。注释也只要一处就可以了,这也避免了彼此同步的问题。IDE【译注:集成开发环境】是可以帮助做这个事的(事实上,我建议他们这么做【译注:此处的“他们”应该是指微软有关人员】),但应该牢记编程上的一个基本原理—尽力做好模拟我们问题空间的抽象。一个支持属性的语言将有助于获得更好的抽象。

 

【作者注:关于属性的这个优点的一个反对意见认为:当采用这种语法时,你搞不清是在操纵一个字段还是属性。然而,在Java(当然也包括C#)中,几乎所有真正复杂一点的类都不会有public的字段。字段一般都只具有尽可能小的访问级别(private/protected,或语言所定义的缺省的),并且只通过获取器和设置器方法暴露,这也意味着你可以获得优美的语法。让IDE解析代码也是完全可行的,可用不同的颜色高亮显示属性,或提供代码完成信息以表明它是否是一个属性。我们还应该看到,如果一个类设计良好,这个类的用户将只关心该类的接口(或规范)【译注:此处是指该类向其客户公开(不单单是public,对其派生类来说,也可能是protected)的方法、属性(C++/Java无显式属性概念)等,这里的客户包括其派生类等等】,而不是其内部实现。另外一个可能的争论是属性不够有效率。事实上,好的编译器可以内联仅返回某个字段的获取器,这和直接访问字段一样快。说到底,即使使用字段要比获取器/设置器来的有效,使用属性还有如下好处—日后可以改变属性的字段【译注:是指可以改变获取器/设置器的实现代码部分,比如改变获取器/设置器里所操作的字段,也可以在获取器/设置器里做一些校验或修饰工作等】,而不会影响依赖于该属性的代码】

 

3.       索引器

 

C#通过提供索引器,可以象处理数组一样处理对象。特别是属性,每一个元素都以一个get或set方法暴露。

 

public class Skyscraper

{

Story[] stories;

public Story this [int index]

{

get

{

return stories [index];

}

set

{

if (value != null)

{

stories [index] = value;

}

}

}

// 其它代码

}

// 实例一个对象

Skyscraper empireState = new Skyscraper (/*...*/);
//
根据索引器来访问对象中的字段

empireState [102] = new Story ("The Top One", /*...*/);

【译注:索引器最大的好处是使代码看上去更自然,更符合实际的思考模式】

 

4.       委托

 

委托可以被认为是类型安全的、面向对象的函数指针,它可以拥有多个方法。委托处理的问题在C++中可以用函数指针处理,而在Java中则可以用接口处理。它通过提供类型安全和支持多方法改进了函数指针方式;它通过可以进行方法调用而不需要内部类适配器或额外的代码去处理多方法调用问题而改进了接口方式。委托最重要用途是事件处理,下一节将通过一个例子加以介绍。
〖译注: 委托又分单播委托和多播委托,多播委托的返回值只能是void声明委托时,CLR其实会为它创建一个类,所以,我们可以理解成声明一个委托的模板类。并且,它可以将函数名将参数传递〗

 

5.       事件

 

C#提供了对事件的直接支持。尽管事件处理一直是编程的基本部分,但令人惊讶的是,大多数语言在正式化这个概念上所做的努力都微乎其微。如果看看现今主流框架是如何处理事件的,我们可以举出如下例子:Delphi的函数指针(称为闭包)和Java的内部类适配器,当然还有Windows API消息系统。C#使用delegate和event关键字提供了一个清爽的事件处理方案。我认为描述这个机制的最好的办法是举个例子来说明声明、触发和处理事件的过程:

 

// 委托声明定义了可被调用的方法签名【译注:这里的签名可以理解为“原型”】

Public delegate void ScoreChangeEventHandler (int newScore, ref bool cancel);

// 产生事件的类

public class Game

{

file://注意使用关键字

public event ScoreChangeEventHandler ScoreChange;

int score;

 

// 属性Score

public int Score

{

get

{

return score;

}

set

{

if (score != value)

{

bool cancel = false;

ScoreChange (value, ref cancel);

if (! cancel)

score = value;

}

}

}

}

 

// 处理事件的类

public class Referee

{

public Referee (Game game)

{

// 监视game中的score的分数改变

game.ScoreChange += new ScoreChangeEventHandler (game_ScoreChange);

}

// 注意这个方法签名和ScoreChangeEventHandler的方法签名要匹配

private void game_ScoreChange (int newScore, ref bool cancel)

{

if (newScore < 100)

System.Console.WriteLine ("Good Score");

else

{

cancel = true;

System.Console.WriteLine ("No Score can be that high!");

}

}

}

 

file://测试类

public class GameTest

{

public static void Main ()

{

Game game = new Game ();

Referee referee = new Referee (game);

game.Score = 70;//【译注:输出 Good Score】

game.Score = 110;// 【译注:输出 No Score can be that high!】

    }

}

 

在GameTest里,我们分别创建了一个game和一个监视game的referee,然后,然后我们改变game的Score去看看referee对此有何反应。在这个系统里,game没有referee的任何知识,任何类都可以监听并对game的score变化产生反应。关键字event隐藏了除了+=和-=之外的所有委托方法。这两个操作符允许你添加(或移去)处理该事件的多个事件处理器。

 

【译注:我们以下例说明后面这句话的意思:

public class Game

{

public event ScoreChangeEventHandler ScoreChange;

protected void OnScoreChange()

{

//在类内,可以这么使用

if (ScoreChange != null)

ScoreChange(30, ref true);

}

 

,但在这个类外,ScoreChange就只能出现在运算符+=和-=的左边】

 

你可能首先会在图形用户界面框架里遇到这个系统。game好比是用户界面的某个控件,它根据用户输入触发事件,而referee则类似于一个窗体,它负责处理该事件。

 

【作者注:委托第一次被微软Visual J++引入也是Anders Hejlsberg设计的,同时它也是造成Sun和微软在技术和法律方面争端的起因之一。James Gosling,Java的设计者,对Anders Hejlsberg曾有过一个故作谦虚听起来也颇为幽默的评论,说他因为和Delphi藕断丝连的感情应该叫他“方法指针先生”。在研究Sun对委托的争执后,我觉得称呼Gosling为“一切都是一个类先生”好像公平些J 过去的这几年里,在编程界,“做努力模拟现实的抽象”已经被很多人代之以“现实是面向对象的,所以,我们应该用面向对象的抽象来模拟它”。

 

Sun和微软关于委托的争论可以在这儿看到:

http://www.Javasoft.com/docs/white/delegates.html http://msdn.microsoft.com/visualj/technical/articles/delegates/truth.asp 】

 

6.       6.枚举

 

枚举使你能够指定一组对象,例如:

声明:

public enum Direction {North, East, West, South};

使用:

Direction wall = Direction.North;

 

这真是个优雅的概念,这也是C#为什么会决定保留它们的原因,但是,为什么Java却选择了抛弃?在Java中,你不得不这么做:

声明:

public class Direction

{

public final static int NORTH = 1;

public final static int EAST = 2;

public final static int WEST = 3;

public final static int SOUTH = 4;

}

使用:

int wall = Direction.NORTH;

 

看起来好像Java版的更富有表达力,但事实并非如此。它不是类型安全的,你可能一不小心会把任何int型的值赋给wall而编译器不会发出任何抱怨【译注:你显然不可以这么写:Direction wall = Direction.NORTH;】。

 

  坦白地说,在我的Java编程经历里,我从未因为该处非类型安全而花费太多的时间写一些额外的东西来捕捉错误。但是,能拥有枚举是一件快事。C#带给你的一个惊喜是—当你调试程序时,如果你在使用枚举变量的地方设置断点,调试器将自动译解direction并给你一个可读的信息,而不是一个你自己不得不译解的数值:

 

声明:

public enum Direction {North=1, East=2, West=4, South=8};

使用:

Direction direction = Direction.North | Direction.West;

if ((direction & Direction.North) != 0)

//....

 

如果你在if语句上设置断点,你将得到一个你可读的direction而不是数值5。

 

【译注:这个例子改一下,会更有助于理解:

声明:

public enum Direction {North=1, East=2, West=4, South=8, Middle = 5/*注意此处代码*/};

使用:

Direction direction = Direction.North | Direction.West;

if ((direction & Direction.North) != 0)

//....

 

如果你在if语句上设置断点,你将得到一个可读性好的direction(即Middle)而不是数值5】

 

【作者注:枚举被Java抛弃的原因极有可能是因为它可以用类代替。正如我上面提到的,单单用类我们不能够象用别的概念一样更好地表达某个特性。Java的“如果它可以用类处理,那就不引入一个新的结构”的哲学的优点何在?看起来最大的优点是简单—较短的学习曲线,并且无需程序员去考虑做同一件事的多种方式。实际上,Java语言在很多方面都以简化为目标来改进C++,比如不用指针,不用头文件,以及单根对象层次等。所有这些简化的共性是它们实际上使得编程—唔—简单了,可是,没有我们刚才提到的枚举、属性和事件等等,反而使你的代码更加复杂了】

 

7.       集合和foreach语句

 

C#提供一个for循环的捷径,而且它还促进了集合类更为一致:

在Java或C++中:

1. while (! collection.isEmpty())

{

Object o = collection.get();

collection.next()

//...

 

2. for (int i = 0; i < array.length; i++)

//...

 

在 C#中:

1. foreach (object o in collection)

//...

 

2. foreach (int i in array)

//...

 

C#的for循环将工作于集合对象上(数组实现一个集合)。集合对象有一个GetEnumerator()方法,该方法返回一个Enumerator对象。Enumerator对象有一个MoveNext()方法和一个Current属性。

 

8.       结构

 

把C#的结构视为使语言的类型系统更为优雅而不仅是一种“如果你需要的话可以利用之写出真正有效率的代码”的概念更好些。

在C++中,结构和类(对象)都可分配在栈或堆上。在C#中,结构永远创建在栈上,类(对象)则永远创建在堆上。使用结构实际上可以生成更有效率的代码:

 

public struct Vector

{

public float direction;

public int magnitude;

}

Vector[] vectors = new Vector [1000];

 

这将把1000个Vector分配在一块空间上,这比我们把Vector声明为类并使用for循环去实例化1000个独立的Vector来得有效率得多。

【译注:因怀疑原文有误,此处故意漏译一句,但不应影响你对这节内容的理解】:

 

int[] ints = new ints[1000];//【译注:此处代码有误,应为int[] ints = new int[1000];】

 

C#完全允许你扩展内建在语言中的基本类型集。实际上,C#所有的基本类型都以结构方式实现的。int型只不过是System.Int32结构的别名,long型不过是System.Int64结构的别名等等。这些基本类型当然可被编译器特别处理,但是语言本身并无区别【译注:意思是语言自身对处理所有类型提供了一致的方法】。在下一节中,我们可看到C#是如何做到这一点的。

 

9.       类型一致

 

大多数语言都有基本类型(int、long等等)。高级类型最终是由基本类型构成的。能以同样的方式处理基本类型和高级类型通常来说是有用处的。例如,如果集合可以象包容sting那样包容int是有用的。为此,Smalltalk通过牺牲些许效率象处理string或Form一样来处理int和long。Java试图避免这个效率损失,它象C和C++那样处理基本类型,但又为每一个基本类型提供了相应的包装类—int包装为Integer,double包装为Double。C++模板参数可接受任何类型,只要该类型提供了模板定义的操作的实现。

 

【译注:在Java中,你可以这么写:

int i = 1;

double d = 1.1;

Integer iObj = new Integer(1);

Double dObj = new Double(1.1);

 

以下写法是错误的:

int I = new int(1);

Integer iObj = 1;

】

 

C#对该问题提供了一个不同的解决方案。在上一节里,我介绍了C#中的结构,指出基本类型不过是结构的一个别名而已。既然结构拥有所有对象类型拥有的方法,那代码就可以这么写:

int i = 5;

System.Console.WriteLine (i.ToString());

如果我们想象使用一个对象那样使用一个结构,C#将为你装箱该结构为对象,当你再次需要使用结构时,可以通过拆箱实现:

 

Stack stack = new Stack ();

stack.Push (i); // 装箱

int j = (int) stack.Pop(); file://拆箱

 

拆箱不仅是类型转换的需要,它也是一个无缝处理结构和类之间关系的方式。你要清楚装箱是做了创建包装类的工作,尽管CLR可以为被装箱的对象提供附加的优化。

 

【译注:可以这么认为,在C#中,对于任何值(结构)类型,都存在如下的包装类:

 

class T_Box     file://T代表任何值类型

{

T Value;

T_Box(T t){Value = t;}

}

当装箱时,比如:

int n = 1;

object box = n;

 

概念上相当于:

int n = 1;

object box = new int_Box(i);

 

当拆箱时,比如:

object box = 1;

int n = (int)box;

 

概念上相当于:

object box = new int_Box(1);

int n = ((int_Box)box).Value; 】

 

【作者注:C#的设计者在设计过程中应该考虑过模板。我怀疑未采用模板有两个原因:第一个是混乱,模板可能很难和面向对象的特性融合在一起,它为程序员的带来了太多的(混乱)设计可能性,而且它很难和反射一起工作;第二点是,如果.NET库(例如集合类)没有使用模板的话,模板将不会太有用。不过,果真.NET类使用了它们,那将有20多种使用.NET类的语言不得不也要能和模板一起工作,这在技术上是非常难以实现的。

 

注意到模板(泛型)已经被Java社团考虑纳入Java语言规范之中是一件有意思的事。或许每个公司都会各唱各的调—Sun说“.NET患了最小公分母综合症”,而微软则说“Java不支持多语言”。

 

(8月10日致歉)看了一个对Anders Hejlsberg的专访后(http://windows.oreilly.com/news/hejlsberg_0800.html),感觉似乎模板已浮出地平线,但第一版没有,正因我们上面提到的种种困难。看到IL规范是如此写法使得IL码可以展现模板(用一个非破坏的方式以让反射可以很好的工作)而字节码则不可以是一件很有趣的事。在此,我还给出了一个关于Java社团考虑要加入泛型的链接:http://jcp.org/jsr/detail/014.jsp 】

 

【译注:此处是上文提到的对Anders Hejlsberg采访的中文版链接:http://www.youkuaiyun.com/develop/article/11/11580.shtm。另外,如欲了解更多关于泛型编程知识,请参见此处链接:http://www.youkuaiyun.com/develop/article/11/11440.shtm】

 

10.   操作符重载

 

利用操作符重载机制,程序员可以创建让人感觉自然的好似简单类型(如int、long等等)的类。C#实现了一个C++操作符重载的限制版,它可以使诸如这样的精辟的例子—复数类操作符重载表现良好。

 

在C#中,操作符==是对象类的非虚的(操作符不可以为虚的)方法,它是按引用比较的。当你构建一个类时,你可以定义你自己的==操作符。如果你在集合中使用你的类,你应该实现IComparable接口。这个接口有一个叫CompareTo(object)方法,如果“this”大于、小于或等于这个object,它应该相应返回正数、负数或0。如果你希望用户能够用优雅的语法使用你的类,你可以选择定义<、<=、>=、>方法。数值类型(int、long等等)实现了IComparable接口。

 

下面是一个如何处理等于和比较操作的简单例子:

public class Score : IComparable

{

int value;

public Score (int score)

{

value = score;

}

 

public static bool operator == (Score x, Score y)

{

return x.value == y.value;

}

 

public static bool operator != (Score x, Score y)

{

return x.value != y.value;

}

 

public int CompareTo (object o)

{

return value - ((Score)o).value;

}

}

 

Score a = new Score (5);

Score b = new Score (5);

Object c = a;

Object d = b;

 

按引用比较a和b:

System.Console.WriteLine ((object)a == (object)b; // 结果为false

 

【译注:上句代码应该为:System.Console.WriteLine ((object)a == (object)b); // 结果为false】

 

比较a和b的值:

System.Console.WriteLine (a == b); // 结果为true

 

按引用比较c和d:

System.Console.WriteLine (c == d); // 结果为false

 

比较c和d的值:

System.Console.WriteLine (((IComparable)c).CompareTo (d) == 0); // 结果为true

 

你还可以向Score类添加<、<=、>=、>操作符。C#在编译期保证逻辑上要成对出现的操作符(!=和==、>和<、>=和<=)必须一起被定义。

 

11.   多态

 

面向对象的语言使用虚方法表达多态。这就意味着派生类可以有和父类具有同样签名的方法,并且父类可以调用派生类的方法【译注:此处应该是对象(或对象引用、指向对象的指针)】。在Java中,缺省情况下方法就是虚的。在C#中,必须使用virtual关键字才能使方法被父类调用。在C#中,还需要override关键字以指明一个方法将重载(或实现一个抽象方法)其父类的方法。

 

Class B file://【译注:应为class B】

{

public virtual void foo () {}

}

Class D : B file://【译注:应为class D : B】

{

public override void foo () {}

}

 

试图重载一个非虚的方法将会导致一个编译时错误,除非对该方法加上“new”关键字,以指明该方法意欲隐藏父类的方法。

Class N : D file://【译注:应为class N : D】

{

public new void foo () {}

}

 

N n = new N ();

n.foo(); // 调用N的foo

((D)n).foo(); // 调用D的foo

((B)n).foo(); // 调用D的foo

 

和C++、Java相比,C#的override关键字使得阅读源代码时可以清晰地看出哪些方法是重载的。不过,使用虚方法有利有弊。第一个有利点是:避免使用虚方法轻微的提高了执行速度。第二点是可以清楚地知道哪些方法会被重载。

 

【译注:从“不过”至此,这几句话显然不合逻辑,但原文就是如此:

  “However, requiring the use of the virtual method has its pros and cons. The first pro is that is the slightly increased execution speed from avoiding virtual methods. The second pro is to make clear what methods are intended to be overridden.”。

  我认为,若将被我标为斜体的method改为keyword的话,逻辑上会顺畅些。这样,第一句话就可认为是和Java比,因其方法缺省是虚的,第二句话主要是和C++比】。然而,利也可能是弊。和Java中缺省忽略final修饰符

 

【译注:在Java中可利用final关键字,对方法上锁,相当于C#/C++中没有用virtual关键字修饰方法/成员函数的情况】以及C++中缺省忽略virtual修饰符相比,Java中缺省选项

 

【译注:即虚的】使得你程序略微损失一些效率,而在C++中,它可能妨碍了扩展性,虽然这对基类的实现者来说,是不可预料的。

 

12.   接口

 

C#中的接口和Java中的接口差不多,但是有更大的弹性。类可以随意地显式实现某个接口:

 

public interface ITeller

{

void Next ();

}

public interface IIterator

{

void Next ();

}

 

public class Clark : ITeller, IIterator

{

void ITeller.Next () {}

void IIterator.Next () {}

}

 

这给实现接口的类带来了两个好处。其一,一个类可以实现若干接口而不必担心命名冲突问题。其二,如果某方法对一般用户来说没有用的话,类能够隐藏该方法。显式实现的方法的调用,需把类【译注:应该是对象】造型转换为接口:

 

Clark clark = new Clark();

 

((ITeller)clark).Next();

 

 

13.   版本处理

 

解决版本问题已成为.NET框架一个主要考虑。这些考虑的大多数都体现于组合体中。在C#中,可在同一个进程里运行同一个组合体的不同版本的能力是令人印象深刻的。

 

当代码的新版本(尤其是.NET库)被创建时,C#可以防止软件失败。C#语言参考里详细地描述了该问题。我用一个例子简明扼要地讲解如下:

 

在Java中,假定我们部署一个称为D的类,它是从一个通过VM发布的叫B的类派生下来的。类D有一个叫foo的方法,而它在B发布时,B还没有这个方法。后来,对类B做了个升级,现在B包括了一个叫foo的方法,新的VM现在安装在使用类D的机器上了。现在,使用D的软件可能会发生故障了,因为类B的新实现可能会导致一个对D的虚函数调用,这就执行了一个类B始料未及的动作。【译注:因Java中方法缺省是虚的】在C#中,类D的foo方法应该声明为不用override修饰符的(这个真正表达了程序员的意愿),因此,运行时知道让类D的foo方法隐藏类B的foo方法,而不是重载它。

 

引用C#参考手册的一句有意思的话“C#处理版本问题是通过需要开发人员明确他们的意图来实现的”。尽管使用override是一个表达意图的办法,但编译器也能自动生成—通过在编译时检查方法是否在执行(而不是声明)一个重载。这就意味着,你仍然能够拥有象Java一样的语言(Java不用virtual和override关键字),并且仍然能够正确处理版本问题。

 

参见字段修饰符部分。

 

14.   参数修饰符

 

(1)ref参数修饰符

C#(和Java相比)可以让你按引用传递参数。描述这一点的最明显的例子是通用交换方法。不象C++,不但是声明时,调用时也要加上ref指示符:【译注:不要误会这句话,C++中当然是没有ref关键字】

 

public class Test

{

public static void Main ()

{

int a = 1;

int b = 2;

swap (ref a, ref b);

}

 

public static void swap (ref int a, ref int b)

{

int temp = a;

a = b;

b = temp;

}

}

 

(2)out参数修饰符

out关键字是对ref参数修饰符的自然补充。Ref修饰符要求参数在传入方法之前必须被赋值。而out修饰符则明确当方法返回时需显式给参数赋值,。

 

(3)params参数修饰符

params修饰符可被加在方法的最后的参数上,方法将接受任意数量的指定类型的参数【译注:在一个方法声明中,只允许一个params性质的参数】。例如:

 

public class Test

{

public static void Main ()

{

Console.WriteLine (add (1, 2, 3, 4).ToString());

}

 

public static int add (params int[] array)

{

int sum = 0;

foreach (int i in array)

sum += i;

return sum;

}

}

 

【作者注:学习Java时一个非常令人诧异的事是发现Java不能按引用传递参数,尽管不久以后,你很少会再想要这个功能,并且写代码时也不需要它了。当我第一次阅读C#规范的时候,我常想,“他们干吗把加上这个功能,没有它我也能写代码”。经过反省以后,我意识到这其实并不是说明某些功能是否有用的问题,更多是说明了没有它你就另需别的条件才能实现的问题。

当考虑到C++是怎么做的时候,Java是干了件好事,它简化了参数如何传递的问题。在C++中,方法【译注:C++中没有方法一说,应该称为“函数”或“成员函数”】的参数和方法调用通过传值、引用、指针【译注:例如int、int*、int&】,使得代码变得不必要的复杂。C#显式传递引用,不管是方法声明时还是调用时。它大大地减少了混乱【译注:这句话应该这么理解:由于C++的语法问题,有时你并不知道你是在使用一个对象还是一个对象引用,本节后有示例】,并达到了和Java同样的目标,但是C#的方式更有表达力。显然这是C#的主旨—它不把程序员圈在一个圈里,使他们必须绕一个大弯子才能做成某件事。还记得Java吗?Java指南里,建议如何解决传引用的问题,你应该传递一个1个元素的数组去保存你的值,或另做一个类以保存这个值。

 

【译注:

 

#include "stdafx.h"

class ParentCls

{

public: virtual void f(){printf("ParentCls/t");}

};

 

class ChildCls : public ParentCls

{

public: virtual void f(){printf("ChildCls/t");}

};

 

void Test1(ParentCls pc) {pc.f();}

void Test2(ParentCls& pc) {pc.f();}

int main(int argc, char* argv[])

{

ChildCls cc;

Test1(cc);//输出ParentCls

Test2(cc);//输出ChildCls

file://只看调用处,是不知道你使用的引用还是对象的,但运行结果迥异!

return 0;

}

】

 

15.   特性

 

C#和Java的编译代码里都包括类似于字段访问级别的信息。C#扩展了这个能力,对类中的任何元素,比如类、方法、字段甚至是独立参数,你都可以编译自定义的信息,并可以于运行时获取这些信息。这儿有一个非常简单的使用特性的类的例子:

 

[AuthorAttribute ("Ben Albahari")]

class A

{

[Localizable(true)]

public String Text file://【译注:应为public string Text或public System.String Text,如果前面没有using System的话】

{

get {return text;}

//...

}

}

 

Java使用一对/** */和@标签注释以包含类和方法的附加信息,但这些信息(除了@deprecated【译注:Java1.1版本及以后】)并未build到字节码中。C#使用预定义的特性Obsolete特性,编译器可以警告你,排除废代码(就象@deprecated),并用Conditional特性使得可以条件编译。微软新的XML库使用特性来表达字段如何序列化到XML中,这就意味着你可以很容易地把一个类序列化到XML中,并可以再次重建它。另外一个对特性的恰当的应用是创建真正有威力的类浏览工具。C#语言规范详尽第解释了怎样创建和使用特性。

 

16.   switch语句

 

C#中的switch语句可以使用整型、字符、枚举或(不象C++或Java)字符串。在Java和C++中,如果你在任何一个case语句里忽略了一个break语句,你就有其它case语句被执行的危险。我想不通为什么这个很少需要的并容易出错的行为在Java和C++中都成了缺省行为,我也很高兴地看到C#不会是这个样子。

 

【译注: 因为C#不支持从一个case标签贯穿到另一个case标签。如果需要的话,可以使用goto case或goto default实现】

 

17.   预定义类型

 

C#基本类型基本上和Java的差不多,除了前者还加入了无符号的类型。C#中有sbyte、byte、short、ushort、int、uint、long、ulong、char、float和double。唯一令人感到惊奇的地方是这儿有一个16个字节【译注:原文误写为12个字节】的浮点型数值类型decimal,它可以充分利用最新的处理器。

 

【译注:补充一下,尽管decimal占用128位,但它的取值范围比float(32位)、Double(64位)远远小得多,但它的精度比后二者的要高得多,可以满足精度要求极高的财务计算等】

 

18.   字段修饰符

 

C#中字段修饰符基本上Java相同。为了表示不可被修改的字段,C#使用const和readonly修饰符。const字段修饰符就象Java的final字段修饰符,该字段的实际值被编译成IL代码的一部分。只读字段在运行时计算值。对标准C#库来说,这就可以在不会破坏你的已经部署的代码的前提下升级。

 

19.   跳转语句

 

这儿没有更多的令人惊讶的地方,可能除了臭名卓著的goto语句。然而,这和我们记得的带来麻烦的20年前的basic的goto语句大不相同。一个goto语句必须指向一个标签【译注:goto语句必须必须在该标签的作用域内,或者换句话说,只允许使用goto语句将控制权传递出一个嵌套的作用域,而不能将控制权传递进一个嵌套域】或是switch语句里的一个选择支【译注:即所谓的goto case语句】。指向标签的用法和continue差不多。Java里的标签,自由度大一些【译注:Java中的break和continue语句后可跟标签】。C#中,goto语句可以指向其作用域的任意一个地方,这个作用域是指同一个方法或finally程序块【译注:如果goto语句出现在finally语句块内,则goto语句的目的地也必须在同一个finally语句块内】。C#中的continue语句和Java中的基本等价,但C#中不可以指向一个标签。

 

【译注:Java把goto作为保留字,但并未实现它】

 

20.   组合体、名字空间和访问级别

 

在C#中,你可以把你源代码中的组件(类、结构、委托、枚举等)组织到文件、名字空间和组合体中。

名字空间不过是长类名的语法上的甜言蜜语而已。例如,用不着这么写Genamics.WinForms.Grid,你可以如此声明类Grid并将其包裹起来:

 

namespace Genamics.WinForms

{

public class Grid

{

//....

}

}

 

对于使用Grid的类,你可以用using关键字导入【译注:即using Genamics.WinForms】,而不必用其完整类名Genamics.WinForms.Grid。

 

组合体是从项目文件编译出来的exe或dll。.NET运行时使用可配置的特性和版本法则,把它们创建到组合体,这大大简化了部署—不需要写注册表,只要把组合体拷到相关目录中去即可。组合体还可以形成一个类型边界,从而解决类名冲突问题。同一组合体的多个版本可以共存于同一进程。每一个文件都可以包含多个类、多个名字空间。一个名字空间可以横跨若干个组合体。如此以来,系统将可获得更大的自由度。

 

C#中有五种访问级别:private、internal、protected、internal protected和public【译注:internal protected当然也可以是protected internal,此外再无其它组合】。private和public和Java中意思一样。C#中,没有标明访问级别的就是private,而不是包范围的。internal访问被局限在组合体中而不是名字空间(这和Java更相似)中。Internal protected等价于Java的protected。protected等价于Java的private protected,而它已被Java废弃。

 

 

21.   指针运算

 

在C#中,指针运算可以被使用在被标为unsafe修饰符的方法里。当指针指向一个可被垃圾收集的对象的时候,编译器强迫使用fixed关键字去固定对象。这是因为垃圾收集器是靠移动对象来回收内存的。但是如果当你使用原始指针时,它所指的对象被移动了,那你的指针将指向垃圾。我认为这儿用unsafe这个关键字是个好的选择—它不鼓励开发人员使用指针除非他们真的想这么做。

 

22.   多维数组

 

C#可以创建交错数组【译注:交错数组是元素为数组的数组。交错数组元素的维度和大小可以不同】和多维数组。交错数组和Java的数组非常类似。多维数组使得可以更有效、更准确地表达特定问题。以下是这种数组的一个例子:

 

int [,,] array = new int [3, 4, 5]; // 创建一个数组

int [1,1,1] = 5;//【译注:此行代码有误:应为array[1,1,1] = 5;】

 

使用交错数组:

int [][][] array = new int [3][4][5]; // 【译注:此行代码有误,应为:int [][][] array = new int[3][][];】

 

int [1][1][1] = 5; 【译注:此行代码有误:应为array[1][1][1] = 5;】【译注:小心使用交错数组】

 

若和结构联合使用,C#提供的高效率使得数组成为图形和数学领域的一个好的选择。

 

 

23.   构造器和析构器

 

你可以指定可选的构造器参数:

class Test

{

public Test () : this (0, null) {}

public Test (int x, object o) {}

}

 

你也可以指定静态构造器:

class Test

{

static int[] ascendingArray = new int [100];

static Test ()

{

for (int i = 0; i < ascendingArray.Length; i++)

ascendingArray [i] = i;

}

}

 

  析构器的命名采用C++的命名约定,使用~符号。析构器只能应用于引用类型,值类型不可以,并且不可被重载。析构器不可被显式调用,这是因为对象的生命期被垃圾收集器所管制。在对象所占用的内存被回收前,对象继承层次里的每一个析构器都会被调用。

 

  尽管和C++的命名相似,C#中的析构器更象Java中的finalize方法。这是因为它们都是被垃圾收集器调用而不是显式地被程序员调用。而且,就象Java的finalize,它们不能保证在各种情况下都肯定被调用(这常常使第一次发现这一点的每一个人都感到震惊)。如果你已习惯于采用确定性的析构编程模式(你知道什么时候对象的析构器被调用),当你转移到Java或C#时,你必须适应这个不同的编程模型。微软推荐的和实现的、贯穿于整个.NET框架的是dipose模式。你要为那些需要管理的外部资源(如图形句柄或数据库连接)的类定义一个dispose()方法。对于分布式编程,.NET框架提供一个约定的基本模型,以改进DCOM的引用计数问题。

 

 

24.   控执行环境

 

对[C#/IL码/CLR]和[Java/字节码/JVM]进行比较是不可避免的也是正当的。我想,最好的办法是首先搞清楚为什么会创造出这些技术来。

 

用C和C++写程序,一般是把源代码编译成汇编语言代码,它只能运行在特定的处理器和特定的操作系统上。编译器需要知道目标处理器,因为不同的处理器指令集不同。编译器也要知道目标操作系统,因为不同的操作系统对诸如如何执行工作以及怎样实现象内存分配这些基本的C/C++的概念不同。C/C++这种模型获得了巨大的成功(你所使用的大多数软件可能都是这样编译的),但也有其局限性:

 

程序无丰富的接口以和其它程序进行交互(微软的COM就是为了克服这个限制而创建的)

程序不能以跨平台的形式分发

不能把程序限制执行在一个安全操作的沙箱里

 

为了解决这些问题,Java采用了Smalltalk采用过的方式,即编译成字节码,运行在虚拟机里。在被编译前,字节码维持程序的基本结构。这就使得Java程序和其它程序进行各种交互成为可能。字节码也是机器中立的,这也意味着同样的class文件可以运行于不同的平台。最后,Java语言没有显式的内存操作(通过指针)的事实使得它很适合于编写“沙箱程序”。

 

最初的虚拟机利用解释器来把字节码指令流转换为机器码。但是这个过程慢得可怕以致于对于那些关注性能的程序员来说,从来都没有吸引力。如今,绝大多数JVM都利用JIT编译器,基本编译成机器码—在进入类框架的范围之前和方法体执行之前。在它运行前,还有可能将Java程序转换为汇编语言,可以避免启动时间和即时编译的内存负担。和编译Visual C++程序相比,这个过程并不需要移去程序对运行时的依赖。Java运行时(这个术语隐藏在术语Java虚拟机下之下)将处理程序执行的很多至关重要的方面,比如垃圾收集和安全管理。运行时也被认为是受控执行环境。

 

尽管术语有点含糊不清,尽管从不用解释器,但.NET基本模型也是使用如上所述方式。.NET的重要的改进将来自于IL自身的设计的改进。Java可以匹敌的唯一方式是修改字节码规范以达到严格的兼容。我不想讨论这些改进的细节,这应该留给那些极个别的既了解字节码也了解IL码的开发人员去讨论。99%的象我这样的开发人员不打算去研究IL代码规范,这儿列出了一些意欲改进字节码的IL设计决策:

 

提供更好的类型中立(有助于实现模板);

提供更好的语言中立;

执行前永远都编译成汇编语言,从不解释;

能够向类、方法等加入附加的声明性信息。参见15.特性;

 

目前,CLR还提供多操作系统支持,而且在其它领域还提供了对JVM的更好的互用性的支持。参见26.互用性。

 

25.   库

 

语言如果没有库那它是没什么用的。C#以没有核心库著称,但它利用了.NET框架的库(它们中的一些就是用C#创建的)。本文着重于讲述C#语言的特别之处,而不是.NET的,那应该另文说明。简单地说,.NET库包括丰富的线程、集合、XML、ADO+、ASP+、GDI+以及WinForm库【译注:现在这些+们多已变成了.NETJ】。有些库是跨平台的,有些则是依赖于Windows的,请阅读下一段关于平台支持的讨论。

 

26.   互用性

 

我认为把互用性分成三个部份论述是比较合适的:de,,并且对那些追求语言互用性、平台互用性和标准互用性。Java长于平台互用性,C#长于语言互用性。而在标准互用性方面,二者都各有长短。

 

(1) 语言互用性

 

和其它语言集成的能力只存在集成度和难易程度的区别。JVM和CLR都允许你用多种语言写代码,只要它们编译成字节码或IL码即可。然而,.NET平台做了大量的工作—不仅仅是能够把其它语言写的代码编译成IL码,它还使得多种语言可以自由共享和扩展彼此的库。例如,Eiffel或Visual Basic程序员可以导入C#类,重载其虚方法;C#对象也可以使用Visual Basic方法(多态)。如果你怀疑的话,VB.NET已经被大幅升级,它已具有现代面向对象特性(付出了和VB6兼容性的损失)。

 

为.NET写的语言一般插入Visual Studio.NET环境中,如果需要的话,可以使用同样的RAD框架。这就克服了使用其它语言是“二等公民”的印象。

 

C#提供了P/Invoke【译注:Platform Invocation Service,平台调用服务】,这比Java的JNI和C代码交互起来要简单得多(不需要dll)。这个特性很象J/direct,后者是微软Visual J++的一个特性。

 

(2) 平台互用性

 

一般而言,这意味着操作系统互用性。但是在过去的几年里,internet浏览器自身已经越来越象个平台了。

 

C#代码运行在一个受控执行环境里。这是使C#能够运行在不同操作系统上的技术重要的一步。然而,一些.NET库是基于Windows的,特别是WinForms库,它依赖于多如牛毛的Windows API。有个从Windows API移植到Unix系统项目,但目前还没有启动,而且微软也没有明确的暗示要这么做。

 

然而,微软并没有忽视平台互用性。.NET库提供了编写HTML/DHTML解决方案的扩展能力。对于可以用HTML/DHTML来实现的客户端来说,C#/.NET是个不错的选择。对于跨平台的需要更为复杂的客户界面的项目,Java是个好的选择。Kylix—Delphi的一个版本,允许同样的代码既可以在Windows上也可以在Linux上编译,或许将来也会成为跨平台解决方案的一个好的选择。

 

(3) 标准互用性

 

几乎所有标准,例如数据库系统、图形库、internet协议和对象通讯标准如COM和CORBA,C#都可以访问。由于微软在制订这些大多数标准上拥有权利或发挥了很大的作用,他们对这些标准的支持就处于一个很有利的位置。他们当然会因为商业上的动机(我没有说他们是否公正)而提供较少的标准支持—对于和他们竞争的东西—比如CORBA(COM的竞争对手)和OpenGL(DirectX的竞争对手)。类似地,Sun的商业动机(再一次,我没有说他们是否公正)意味着Java不会尽其所能地支持微软的标准。

 

由于C#对象被实现为.NET对象,因此它自动暴露为COM对象。C#因此就既可以暴露COM对象也可以使用COM对象。这样,就可以集成COM代码和C#项目。.NET是一个有能力最终替代COM的框架—但是,已经有那么多已部署的COM组件,我相信,不等.NET取代掉COM,它已经被下一波技术所取代了。但无论如何,希望.NET能有一个长久而有趣的历史!J

 

27.   结论

 

到此为止,我希望已给了你一个C#与Java、C++在概念上的比较。总的来说,比起Java,我相信C#提供了更好的表达力并且更适合编写对性能有严格要求的代码,它也同样具有Java的优雅和简单,这也是它们都比C++更具吸引力之处。

 

—全文完—

 
c#实现科学计算器 —— 总体分析篇 引言   早在一年前,我就用VC++设计了一个能够计算表达式的科学计算器,但由于当时才大二,对于“编译原理”这种东西根本就没有概念,因此设计时遇到了有关错误文法分析的问题(当时只知道要在用户输入不正确的表达式格式时报错),不知道怎么做,因此就把这个项目搁置了下来,本学期正好学到编译原理,发现还是可以用一些理论化的东西来解决文法问题,于是决定重新启动这个项目,并把代码移植到C#中。 设计 阅读详情

相关推荐

计算样本标准差和总体标准差的C#基础教程

然后,我们分别调用CalculateSampleStandardDeviation方法和CalculatePopulationStandardDeviation方法来计算样本标准差和总体标准差,并将结果打印到控制台。样本标准差是基于数据集中的一部分样本计算得出的,而总体标准差则是基于整个数据集计算得出的。最后,我们使用Math.Sqrt方法计算方差的平方根,得到样本标准差(standardDeviation),并将其作为方法的返回值。使用上述代码,我们可以轻松地计算给定数据集的样本标准差和总体标准差。

CodeBandit的博客 518

C# 和 Java相同点和不同点总结

1、C# 和 Java 都需要编译成中间代码,因此Java和C#性能上通常不如C++这类编程语言。(Java由javac编译成字节码,然后再由解释器逐条将字节码解释为机器码来执行。C#通过特定语言编译器将代码编译成 IL( intermediate language),然后通过 JIT(Just In Time) 将IL 翻译成机器码来执行。)2、C# 和 Java 都是面向对象编程的语言,都能够实现面向对象的(封装,继承,多态)思想。3、C# 和 Java都支持跨平台。

djwuhjwiwhe的博客 1715

基于C#的工业测试控制软件-总体框架

目前工业控制领域域中,经常采用C#/.net开发工业控制平台,本专栏从实战架构出发,深入解析K设计原理及架构,本专栏跳过基础语法描述,重点从业务领域出发,深入解析整体设计框架。

whm128的博客 679

JAVA注解和C#特性

关键词: C#: Attribute:特性(HTML标签叫属性) Property:属性 Usage:使用、用法、习惯、惯例 AttributeUsage:特性用法(个人翻译) Obsolete:过期 (C#中代表过期,不推荐使用) Conditional:条件JAVA: Annotation:注释 Deprecated:反对,不赞成(JAVA代表过期,不推荐使用) Supres

qqqqqqqq188的专栏 7324

PX4实战指南:通过遥控器通道直连实现舵机PWM控制

本文详细介绍了如何通过PX4飞控实现遥控器通道直连控制舵机PWM输出的完整流程。从硬件准备、遥控器配对到PX4参数配置和硬件连接,提供了实战技巧和常见问题解决方案,帮助无人机爱好者快速掌握舵机控制技术。重点讲解了AUX Passthrough模式设置和PWM参数调整等关键步骤。

weixin_29195217的博客 154

【一键搞定】ThinkPHP6.0.2+PHPStudy+Composer极速安装指南——附完整下载包与避坑技巧

本文提供了一份ThinkPHP6.0.2的完整下载包,并详细介绍了如何配合PHPStudy和Composer进行极速安装与配置。指南涵盖了环境准备、Composer国内镜像加速、项目部署及常见避坑技巧,旨在帮助开发者,尤其是内网或网络不佳的用户,快速搭建可运行的TP6开发环境,绕过依赖下载的繁琐步骤。

assembly8low的博客 1008

C#学习(十六)——基于C#与OpenCVSharp的图像处理软件

基于OpenCVSharp的图像处理软件: https://blog.youkuaiyun.com/you_big_father/article/details/86088531?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-9.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMach

lvjiyang的博客 1309

LibTV本地部署:AI漫剧创作完整解决方案与实战指南

如果你正在关注AI漫剧创作这个赛道,可能会发现一个有趣的现象:市面上的AI视频工具要么功能单一,要么云端服务昂贵且存在内容审核风险。而今天要介绍的LibTV本地部署方案,或许能为你打开一扇新的大门。 这个方案的核心是Seedance2.0与豆包AI的本地化集成,它真正解决的是创作者对内容自主权、成本控制和创作效率的三重需求。与红果、抖音等平台提供的标准化AI工具相比,本地部署意味着你可以完全掌控生成过程,不受平台规则限制,更重要的是——所有数据都在本地,不存在内容泄露风险。 1. 这篇文章真正要解决的问题

weixin_28745309的博客 523

c#程序设计实训报告心得体会_C程序设计实训个人总结(推荐五篇)

通过上个学期的C语言学习之后,这学期我开始了C语言的实训。这次实训一共有12道题,可以说这12道题要运用学过的所有C语言知识。刚开始的两天,由于长时间没有接触这科,所以编程的时候有一些困难,通过课下的复习我逐渐开始适应编程的节奏。这一周的编程我对于之前不怎么熟悉的语句逐渐熟悉了,通过不断的调试过程,我改正了编程的一些毛病,对于之后的实训有很大的帮助。我认为学习c语言不能停留在学习它的语法规则,而是...

weixin_39796752的博客 1万+

DPO(Direct Preference Optimization)直接偏好优化

本文介绍了DPO(直接偏好优化)方法,该方法通过简化传统的RLHF(基于人类反馈的强化学习)流程,直接利用人类偏好数据进行模型优化。DPO的核心思想是跳过奖励模型训练和强化学习交互步骤,通过数学推导将优化目标转化为仅与策略概率分布相关的形式。推导表明最优策略与奖励模型之间存在显式关系,从而可以构建直接优化策略的损失函数。与RLHF相比,DPO简化了训练流程,提高了工程实现稳定性,同时保持了同等效果。

TeenLucifer的博客 1956

SQL手工注入及sqlmap注入(文章管理系统实例练习)

sql手工注入及sqlmap注入练习

weixin_53303754的博客 523

C#基础_C#计算样本标准差和总体标准差

样本标准差=方差的算术平方根=s=sqrt(((x1-x)^2 +(x2-x)^2 +......(xn-x)^2)/(n-1))总体标准差=σ=sqrt(((x1-x)^2 +(x2-x)^2 +......(xn-x)^2)/n )上面的数据是用Excel来计算的,方便对我们软件输出的数据做对比。了解了基本概念,下面就是C#代码了,在窗体创建一个按钮来测试。这个是excel里对标准差函数的使用方法。

qq_43379938的博客 1619

S7-200 SMART Modbus RTU从站配置与调试实战指南

本文提供了一份详细的S7-200 SMART PLC配置为Modbus RTU从站的实战指南。内容涵盖从硬件基础、软件准备、指令库调用、核心编程到地址映射与调试排错的完整流程。重点解析了MBUS_INIT与MBUS_SLAVE指令的关键参数配置,并深入探讨了Modbus地址与PLC内部V存储区的对应关系,帮助工程师快速打通通讯链路,实现与上位机、触摸屏等主站设备的稳定数据交互。

potato的博客 753

C# 及excel中【总体方差】、【样本方差】的计算公式

【总体方差】和【样本方差】是不同的概念,在计算【方差】的时候需要明确你要计算的是什么方差,同样,在用Excel进行手工验算的时候,也要注意公式

穿裤子的云 3786

Jetson agx Orin 适配Xenomai4

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。

xiaoning132的专栏 465

2025年11月架构设计师综合知识真题回顾,附参考答案、解析及所涉知识点(二)

本文整理了2025年11月架构设计师考试的16-30题真题及解析,涵盖多个计算机系统知识领域。主要内容包括:Linux绝对路径以根目录开始(A);模块调用下层数量用扇出表示(B);游乐园问题通过集合运算得出10人未游玩(B);磁盘位示图计算为200字节(C);测试用例核心是输入与预期输出(D)。其他题目涉及软件可靠性测试概念(B错)、评价程序准确度排序(真实程序最高,A)、测试阶段顺序(单元→组装→系统,A)、Web服务器压力测试前置步骤(C)、分时系统响应时间影响因素(用户数量多,A)、逆向工程方法(基于

一几文的编程学习笔记。 225

C#总体概况

C#语言整理 输入输出--数据类型--变量与常量--运算符表达式--语句(顺序、分支、循环)--数组--函数--结构体一、输入与输出。Console.ReadLine();Console.WriteLine();Console.Write(); 二、数据类型:(一)分类:1.值类型:基本类型:int(short long),double(float decimal),bool,c...

109

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

在C#中的使用Measurement Studio 之一 总体介绍

最近写上位机界面,看见一个比较好的工具,现在来介绍给大家,Measurement Studio 2010 是NI公司的一款软件,具体的百度。 2010版只支持C# 和VB,我以前只用MFC的只能悲剧,不过以前的版本到时可以用MFC写,看一下界面的样子,绝对的给力。 官网移步:点击打开链接 百度的介绍移步:点击打开链接 具体的写教程需要一步步学习,然后再写出来,发布时间看天气预报

To be better 9299

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

C#的书籍/总体布局和规划/主体学习方法研究报告

这篇文章是我在2007年5月14~22日分段发表在优快云的C#专题研究群组的,8月份做了合并。2007年2月19日开始自学程序设计。5月份开始学习上网,出于一种对于狂热的学习程序设计兴奋的心情,想和群友做一些互动交流和摸索怎样发表文章,就把自己的想法发表了出来。那时候只有七本C#的书籍,现在有44本了,考察得较为全面些,所以,以现在的眼光看来,有一些看法是需要修正的。不过此处只是出于管理的方便,

Ltaos的专栏 1131

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

C#日期函数总体应用

C#日期格式化 日期转化一为了达到不同的显示效果有时,我们需要对时间进行转化,默认格式为:2007-01-03 14:33:34 ,要转化为其他格式,要用到DateTime.ToString的方法(String, IFormatProvider),如下所示:using System;using System.Globalization;String format

laolai13的专栏 452

【C#】初了解

感悟:                C#看完一半了,总体的感觉是很基础,很简单,很细致,但同时很琐碎,看完很简单,理解也很容易,但是想要把这些知识抓起来就没那么容易啦,跟师傅聊了聊之后,也给大家一个建议,就是在看视频之前先看一本相关的书。          在我看来,并不是什么项目都适合先看书,首先,视频和书籍更多的人更倾向于看视频,其次我认为像UML这类的视频,视频本身就系统性非常强,脉络

向阳而生 895

浅学C#(4)——总体框架、关键字、命名规则、代码规范

总体框架 Hiker.cs 类名不一定等于文件名 using System; //每一个程序必须在开头使用这一语句 public sealed class HitchHiker { public static void Main()//程序从Main开始执行 { int result; result ...

衡与墨的博客 692

北京城市总体总体规划 下载_总体表现

北京城市总体总体规划 下载 While reading EricGu’s post on Performance of Generics, I was struck by this sentence which expresses perfectly what I was trying to express to a group of program...

cunfuxiao7305的博客 84

C#课程设计 ——小游戏打地鼠

期末课程设计,简单易懂。打地鼠的界面分为三部分,第一部分最上面的显示栏部分,中间是游戏界面部分,最下面是设置栏按钮部分。利用Visual Studio 2012 Windows窗体应用程序首先开始设计一个整体的界面,菜单栏中分别有:打中次数、总点击数、剩余时间。显示部分由登录界面的图片以及生成界面组成,定义打地鼠所需要的按钮并赋给其按钮名称,使得使用打地鼠游戏简单明了,清晰可见,操作轻松。

qq_51014165的博客 4715

C#对Java

C#对Java C#(C-Sharp)是Microsoft的新编程语言,被誉为“C/C++家族中第一种面向组件的语言”。然而,不管它自己宣称的是什么,许多人认为C#更像是Java的一种克隆,或者是Microsoft用来替代Java的产品。事实是否是这样的呢?  本文的比较结果表明,C#不止是Java的同胞那么简单。如果你是一个Java开发者,想要学习C#或者了解更多有关C#的知识,那么本文就是你必

sugar88的学习收集专栏 873
上一篇: 面试技巧
下一篇: 关于C#装箱与拆箱的研究
LEOlws
博客等级 码龄21年 9粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值