.net深入体验与实战精要--细节决定成败
1.Equals()和运算符==的区别
因为值类型是存储在内存中的堆栈(下面简称栈),而引用类型的变量在栈中仅仅存储引用类型的地址,其本身则存储在堆中。
{
int n1 = 1;
int n2 = 1;
Console.WriteLine(n1 == n2);//true
Console.WriteLine(n1.Equals(n2));//true
//
string s1 = "test";
string s2 = "test";
Console.WriteLine(s1 == s2);//ture
Console.WriteLine(s1.Equals(s2));//我认为false,但是结果是true
string s3 = s1;
Console.WriteLine(s3 == s1);//true
Console.WriteLine(s3.Equals(s1));//true
Console.WriteLine(s3 == s2);//true
Console.WriteLine(s3.Equals(s2));//我认为false,但是结果是true
Console.ReadKey();
}
public class ClassPerson
{
public ClassPerson(string strname)
{
name = strname;
}
private string name = null;
public string Name
{
set { name = value; }
get { return name; }
}
}
class Program
{
static void Main(string[] args)
{
string s1 = "test";
string s2 = "test";
Console.WriteLine(s1 == s2); //True
Console.WriteLine(s1.Equals(s2)); //True
object o1 = s1;
object o2 = s2;
Console.WriteLine(o1 == o2); //True
Console.WriteLine(o1.Equals(o2)); //True
string s3 = new string(new char[] { ‘t‘, ‘e‘, ‘s‘, ‘t‘ });
string s4 = new string(new char[] { ‘t‘, ‘e‘, ‘s‘, ‘t‘ });
Console.WriteLine(s3 == s4); //True
Console.WriteLine(s3.Equals(s4)); //True
object o3 = s3;
object o4 = s4;
Console.WriteLine(o3 == o4); //False
Console.WriteLine(o3.Equals(o4)); //True
ClassPerson p1 = new ClassPerson("ltp");
ClassPerson p2 = new ClassPerson("ltp");
Console.WriteLine(p1 == p2); //False
Console.WriteLine(p1.Equals(p2)); //False
ClassPerson p3 = new ClassPerson("ltp");
ClassPerson p4 = p3;
Console.WriteLine(p3 == p4); //True
Console.WriteLine(p3.Equals(p4)); //True
Console.ReadKey();
}
}
2.const和readonly的区别
- readonly和const都是用来表示常量的
- 初始化赋值不同
public class Class1
{
public const int va=10;//正确
public const int vb;// 错误
public Class1()
{
vb=10;
}
}
//readonly 字段可以在初始化(声明或构造函数)的过程中赋值,在其他地方不能赋值
public class Class1
{
public readonly int i=10;//right
public readonly int z;
public Class1()
{
z=1;//right;
}
protected void Load()
{
z=1;//wrong 无法对制度的字段赋值(构造函数或变量出事值制定项中除外)
}
}
- const是编译时的常数,readonly字段可荣誉运行时常数
//right
public const int n=1;
public const int m=n+1;
//wrong
public const int a;
public const int b=a+1;
- readonly是计算时执行的。
public static readonly uint nowtime=(uint)DateTime.Now.Ticks;
public static readonly string ConnectionString=Configuration.AppSettings["SQLConnectring"];
- const默认就是静态的,而readonly如果设置成静态的就必须显示声明
- object,Array(数组)和struct(结构)不能被声明为const常量
- const和static readonly
sealed,new,virtual,abstract与override
- sealed——断子绝孙
- new——你是你的,我是我的
- virtual——为了子孙后代
- abstract——我是上帝
- override——一手遮天
public class BaseClass
{
public BaseClass()
{
Console.WriteLine(" 基类构造");
}
public virtual void Method() //使用virtual才可以在子类中使用override,而new不必要
{
Console.WriteLine(" 基类.Method()");
}
}
public class DeriveClassA : BaseClass
{
public DeriveClassA()
{
Console.WriteLine(" 类A.构造");
}
public override void Method()
{
//base.Method();
Console.WriteLine(" 类A.Method() in override");
}
}
public class DeriveClassB : BaseClass
{
public DeriveClassB()
{
Console.WriteLine(" 类B.构造");
}
public new void Method()
{
//base.Method();
Console.WriteLine(" 类B.Method() in new");
}
}
class Program
{
static void Main(string[] args)
{
BaseClass ba1 = (BaseClass)new DeriveClassA();//类型转换
ba1.Method(); //用override重写方法,是基类的一个派生,所以这里通过基类的虚函数,会访问到派生类的方法。
Console.WriteLine(" =================");
BaseClass bb2 = (BaseClass)new DeriveClassB();
bb2.Method(); //用new重写方法,是一个和基类无关的新方法,所以这里基类调用的时候,访问基类的方法。
Console.WriteLine(" =================");
DeriveClassA a1 = new DeriveClassA();
a1.Method();
Console.WriteLine(" =================");
DeriveClassB b2 = new DeriveClassB();
b2.Method();
Console.WriteLine(" =================");
Console.ReadKey();
}
}
公共变量与属性的区别
成员变量
public string Name
类属性
public class People
{
private string name;
public string Name
{
set
{
name=value;
}
get
{
return name;
}
}
}
总结:
- 属性是对字段的封装
- 属性可以控制读写,变量不可以
- 属性可以进行操作,变量不可以
参数修饰符params,out和ref的区别
params——一个可以唱方法拥有的可变参数的关键字
public class Program
{
static void UseParams(params int[] list)
{
string temp = "";
for (int i = 0; i < list.Length; i++)
{
temp = temp + " " + list[i].ToString();
}
Console.WriteLine(temp);
}
static void UseParams2(params object[] list)
{
string temp = "";
for (int i = 0; i < list.Length; i++)
{
temp = temp + " " + list[i].ToString();
}
Console.WriteLine(temp);
}
static void Main()
{
UseParams(1, 2, 3);//看参数是3个
UseParams(1, 2); //看参数是2个,可变吧
UseParams2(1, ‘a‘, "test");
int[] myarray = new int[3] { 10, 11, 12 };
UseParams(myarray); //看也可以是容器类,可变吧:)
Console.ReadKey();
}
}
out——一个引用参数
当一个方法在使用out作为参数时,在方法中对out参数所做的任何改变都将方应在变量中
static void Main()
{
int value;//不必初始化
Method(out value);//显示使用out关键字
Console.WriteLine(value);//value is now 44
}
static void Method(out int i)
{
i=44
}
当希望方法返回多个值时,声明out方法非常有用。
static void Main()
{
int value;
string str1,str2;
Method(out value,out str1,out str2);
Console.WriteLine(value);
Console.WriteLine(str2);
Console.WriteLine(str3);
}
static void Method(out int i , out string s1,out string s2)
{
int 1=44;
s1="返回第二个参数";
s2=null;
}
若要使用out参数,则方法定义和调用方法都要显式使用out关键字。
不必初始化作为out参数传递的变量,ref要求变量必须在传递之前进行初始化
属性不是变量不能作为out参数传递
如果两个方法的声明仅在out的使用方面不同,则会发生重载,不过无法定义仅在ref和out方面的不同重载,例如如下是有效的
class MyClass
{
public void MyMethod(int i)
{
i=10;
}
public void MyMethod(out int i)
{
i=10;
}
}
而下面是无效的
class MyClass
{
public void MyMethod(out int i)
{
i=10;
}
public void MyMethod(ref int i)
{
i=10;
}
}
ref——仅仅是一个地址
当一个方法在使用ref作为参数时,在方法中对ref参数所做任何改变都反映在改变量中
static void Main()
{
int value=0; //必须初始化
Method(ref value); //显式使用ref关键字
Console.Write(value); //value is now 44
}
static void Method(ref int i)
{
i=44;
}
同样的下面的是有效的
class MyClass
{
public void MyMethod(int i)
{
i=10;
}
public void MyMethod(ref int i)
{
i=10;
}
}
而下面的是无效的
class MyClass
{
public void MyMethod(out int i)
{
i=10;
}
public void MyMethod(ref int i)
{
i=10;
}
}
ref和out示例
public static string TestOut(out string i)
{
i="out b";
return "return value";
}
public static void TestRef(ref string i )
{
//改变参数
i="ref b"
}
public static void TestNoRef(string refi)
{
//不用改变任何东西
refi="on c";
}
static void Main()
{
string outi ;//不需要初始化
Console.Write(TestOut(out outi));//返回值 输入“return value”
Console.Write(outi);
string refi ="a";//必须初始化
TestRef(ref refi);
Console.WriteLine(refi);//输出ref b
TestNoRef(refi);//不适用ref
Console.WriteLine(refi) //仍然输出ref b 没变
}
值类型和引用类型的区别
类和结构的区别
一个是引用类型,一个是值类型
继承性——struct没有继承性,但是结构可以实现接口
interface IPerson
{
void eat();
}
struct Man:IPerson
{
public void eat()
{
//实现接口
}
private int x,y,z;//其他结构成员
}
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。