重读 c#入门经典 (2)
重读 c#入门经典 (2) [1-13] 基础知识
P58:
在switch 中用 return语句,中断当前函数的运行,远胜于中断switch结构的执行.
P59:
const int i=2; (对)
------
const int i;
i=2;
(错)
--------------------------------------------
枚举:http://www.cftea.com/c/2008/02/I2Y6LWL02XCILMWE.asp
http://blog.csdn.net/williamzao/archive/2008/03/02/2139648.aspx
enum Color: long
{
Red,
Greeen,
blue
}
[Flags]
public enum WindowStyle
{
MINIMUM_BUTTON = 1, //十六进制表示为 0x0001
MAXIMUM_BUTTON = 2,
CLOSE_BUTTON = 4
}
我们在设置窗口样式时,利用 OR 自由组合:
WindowStyle ws = WindowStyle.MINIMUM_BUTTON | WindowStyle.CLOSE_BUTTON; //表示既有 MINIMUM_BUTTON 也有 CLOSE_BUTTON
这就是为什么标志的值要按 2 的幂排列的原因了,也是为什么标志多于 32 个时不能使用 int 类型的原因了。
通常我们为常用的标志组合提供特殊的枚举值
仍然以上述窗口为例,可知大多数情况下,我们均要显示这三个按钮,所以每次使用时都要用:
WindowStyle ws = WindowStyle.MINIMUM_BUTTON | MAXIMUM_BUTTON | WindowStyle.CLOSE_BUTTON;
实在有些繁琐,我们可以修改枚举为如下:
[Flags]
public enum WindowStyle
{
MINIMUM_BUTTON = 1,
MAXIMUM_BUTTON = 2,
CLOSE_BUTTON = 4,
ALL_BUTTON = 7
}
增加一个 ALL_BUTTON 为前三个标志的值。使用时直接用 ALL_BUTTON 就可以了
P88:
int[] myIntArray = {5,5,8,7,89,4};
---------------
int[] myIntArray = new int[5];
这里使用关键字 new 显式地初始化数组,用一个常量定义其大小,这种方式会给所有的数组元素赋予同一个默认值,对于数值类型来说,其默认值是0;
----------------------------------
p92 p93 多维数组,数组的数组.
int[,] iAry = { {1,2,3},{4,8,9},{5,4,8}};
//这里不用嵌套
foreach (int j in iAry)
{
Console.WriteLine(j.ToString() + ",");
}
-----------------
int[][] i;
i = new int[2][3];
--错
int[][] i={{1,1},{2,2},{1,3}};
--错
初始化数组的数组(锯齿数组)应该这样:
int[][] i;
i = new int[2][];
i[0] = new int[10];
i[1] = new int[5];
或
i = new int[2][] { new int[]{1,2,1},new int[]{5,4,4}};
或
int[][] i = new int[2][] { new int[]{1,2,1},new int[]{5,4,4}};
或
int[][] i = { new int[]{1,2,1},new int[]{5,4,4}};
------------------------------------------------------
p108:
params 参数必须是形参的最后一个参数.
private void button1_Click(object sender, EventArgs e)
{
Doit(1, 2, 3, 3, 4, 4, 23.0,"sf",32);
}
public void Doit(params object[] oParam)
{
int iSum = 0;
foreach (object o in oParam)
{
if (o is int)
{
iSum += Convert.ToInt32(o);
}
}
Console.WriteLine(iSum.ToString());
}
p109:
out与ref 区别
方法参数上的 out 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。
当希望方法返回多个值时,声明 out 方法非常有用。使用 out 参数的方法仍然可以返回一个值。一个方法可以有一个以上的 out 参数。
若要使用 out 参数,必须将参数作为 out 参数显式传递到方法。out 参数的值不会传递到 out 参数。
不必初始化作为 out 参数传递的变量。然而,必须在方法返回之前为 out 参数赋值。
属性不是变量,不能作为 out 参数传递。
方法参数上的 ref 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。
若要使用 ref 参数,必须将参数作为 ref 参数显式传递到方法。ref 参数的值被传递到 ref 参数。
传递到 ref 参数的参数必须最先初始化。将此方法与 out 参数相比,后者的参数在传递到 out 参数之前不必显式初始化。
属性不是变量,不能作为 ref 参数传递。
两者都是按地址传递的,使用后都将改变原来的数值.rel可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个数值从out传递进去的,out进去后,参数的数值为空,所以你必须初始化一次
rel是有进有出,out是只出不进
p163 引用类型与值类型比较
http://www.tracefact.net/CSharp-Programming/Type-Fundamentals.aspx
http://www.cnblogs.com/lynnlin/archive/2008/11/18/1335741.html
string 类型精讲
http://www.cnblogs.com/isline/archive/2009/02/04/1383835.html
http://www.cnblogs.com/KissKnife/archive/2008/10/25/1319352.html
String.Intern 方法
返回值
类型:System..::.String
如果 str 的值已经留用,则返回系统的引用;否则返回对带有 str 值的字符串的新引用。
事实上这里涉及到一个所谓的“字符串留用”机制,根据Jeffrey Richter在《框架设计:CLR via C#》中所说,CLR存在一种机制,当它初始化时,它会创建一个内部哈希表,此表中key是字符串,value是对托管堆中的string对象的引用。当定义一个string 时,就会在内部哈希表中检查是否有相匹配的。如果不存在完全相同的字符串,就创建字符串副本,将字符串副本添加到内部哈希表中,并返回这个副本的引用。如果存在完全相同的字符串,就返回对现有字符串的引用。
深度拷贝与浅度拷贝
http://www.tracefact.net/CSharp-Programming/Type-Fundamentals.aspx
p177,p178
构造函数
p180 vs ide 中的符号.
public
private
internal
protected
abstract :抽象,没有方法体的虚拟
virtual :可以被重写的方法.虚拟
多态:
编绎时多态:重载(overload)
运行时多态:覆写(overrite)(重写)
封装性最有用的方式之一
实现方法--访问限制修饰符
public 无限制,允许任何人来访问
protected internal = protected + internal
Internal 允许项目或程序内部的类来访问
protected 继承时子类可以对基类有完全访问权
private 只允许同一个类中的成员访问
属性和索引器也用来封装类的细节,并提供公用接口给该类的用户
防止继承
public sealed class XX
只有虚方法和抽象方法才能被覆写
要求: (三相同)
相同的方法名称
相同的参数列表
相同的返回值类型
抽象方法是必须被派生类覆写的方法。
抽象方法是可以看成是没有实现体的虚方法
如果类中包含抽象方法,那么类就必须定义为抽象类,不论是否还包含其它一般方法
publc abstract bool Withdraw(…);
p207:嵌套类的功能主要用于定义对于其包含类来说是私有的类,这样命名空间中的其他代码就不能访问它.
p208:实现接口的类必须包含该接口所有成员的执行代码,且必须匹配指定的签名(包括匹配指定的get和set块),并且必须是公共的.
显式实现接口的话,只能使用接口变量调用方法;非显式的话,还可以通过类的实例对接口定义的方法进行调用(也可以用接口变量)
public interface IMyInterface
{
void Print();
}
class MyClass : IMyInterface
{
void IMyInterface.Print()//显式实现接口
{
Console.WriteLine("Print--------------");
}
}
调用:
IMyInterface my = new MyClass();
my.Print();
------------------
public interface IMyInterface
{
void Print();
}
public class MyClass : IMyInterface
{
public void Print()
{
Console.WriteLine("Print--------------");
}
public string ssss = "";
}
调用:
IMyInterface my = new MyClass();
my.Print();
或
MyClass my = new MyClass();
my.Print();
http://www.builder.com.cn/2008/0521/872547.shtml
---------------------------------------------------------
11章:集合比较转换
哈希函数是一个映象,即:将关键字的集合映射到某个地址集合上,它的设置很灵活,只要这个地址集合的大小不超出允许范围即可。
散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表.
强类型:
所谓的强类型对象就是说声明一个对象必须要有一个特定的类型,比如int i = 1; string s ="123";,强类型是对应弱类型而言的,比如javascript就是弱类型,声明一个int变量与声明一个字符串类型都是一样的var i = 1; var s = "123";
C#本身是一种强类型的语言。
所以这类语言中,所有建立的对象都要声明类型
强类型,就是对变量指定数据类型。
c#中所变量都是指定类型的,所以大家都说 all 。
-----------------------------------------
索引:
http://www.goalercn.com/article.php?id=1620
定义索引指示器时,可以带有多个参数,每个参数的类型可以不同。添加的参数由逗号隔开,同方法中的的参数表一样。索引指示器的合法的参数类型包括:整型,枚举类型和字符串。另外,索引指示器也可以被重载
public object this[int param1, ..., int paramN]
{
get
{
// process and return some class data
}
set
{
// process and assign some class data
}
}
----------------------------------------
迭代器Iterators
迭代器是 C# 2.0 中的新功能。迭代器是方法、get 访问器或运算符,它使您能够在类或结构中支持 foreach 迭代,而不必实现整个 IEnumerable 接口。您只需提供一个迭代器,即可遍历类中的数据结构。当编译器检测到迭代器时,它将自动生成 IEnumerable 或 IEnumerable<T> 接口的 Current、MoveNext 和 Dispose 方法。
迭代器概述
-
迭代器是可以返回相同类型的值的有序序列的一段代码。
-
迭代器可用作方法、运算符或 get 访问器的代码体。
-
迭代器代码使用 yield return 语句依次返回每个元素。yield break 将终止迭代。有关更多信息,请参见 yield。
-
可以在类中实现多个迭代器。每个迭代器都必须像任何类成员一样有唯一的名称,并且可以在 foreach 语句中被客户端代码调用,如下所示:foreach(int x in SampleClass.Iterator2){}
-
迭代器的返回类型必须为 IEnumerable、IEnumerator、IEnumerable<T> 或 IEnumerator<T>。
yield 关键字用于指定返回的值。到达 yield return 语句时,会保存当前位置。下次调用迭代器时将从此位置重新开始执行。
迭代器对集合类特别有用,它提供一种简单的方法来迭代不常用的数据结构(如二进制树)。
示例
在本示例中,DaysOfTheWeek 类是将一周中的各天作为字符串进行存储的简单集合类。foreach 循环每迭代一次,都返回集合中的下一个字符串。
public class DaysOfTheWeek : System.Collections.IEnumerable { string[] m_Days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" }; public System.Collections.IEnumerator GetEnumerator() { for (int i = 0; i < m_Days.Length; i++) { yield return m_Days[i]; } } } class TestDaysOfTheWeek { static void Main() { // Create an instance of the collection class DaysOfTheWeek week = new DaysOfTheWeek(); // Iterate with foreach foreach (string day in week) { System.Console.Write(day + " "); } } }
输出
Sun Mon Tue Wed Thr Fri Sat
public static C1 operator +(C1 a, C1 b)
{
C1 t = new C1();
t.TestTest = a.TestTest + b.TestTest;
return t;
}
public static bool operator true(C1 p)
{
return p.TestTest >= 0;
}
public static bool operator false(C1 p)
{
return p.TestTest < 0;
}
--------------------------
IComparable
(obj.CompareTo(object o))
,IComparer
(obj.Compare(object x,object y)
http://space.itpub.net/12639172/viewspace-483585
----------------------------------------
显式转换:explicit
隐式转换:implicit
http://www.cnblogs.com/jonney/archive/2007/04/17/716645.html
--------------------------
p267
as 运算符:适用于:
<operand> as <type>
1,<operand>的类型是<type>类型.
2,<operand>可以隐式转换为<type>类型.
3,<operand>可以封箱到类型<type>中.
如果不能从<operand>转换为<type>,则表达式的结果就是null.