理解值和引用-第八章-C#从入门到放弃

Circle c;
c = new Circle(42);
Circle refc;
refc = c;  //c与refc指向同一地址

正确的复制类的方法(包括复制私有数据):

class Circle
{
    private int radius;
    ...
    public Circle Clone()
    {
        //创建新的Circle对象
        Circle clone = new Circle();
        //将私有的数据从this复制到clone
        clone.radius = this.radius;
        
        //返回包含克隆数据的新Circle对象
        return clone;
    }
}

null值:

Circle c = new Circle(42);
Circle copy = null;
...
if(copy == null)
{
    copy = c;
    ...
}

对于值类型,需要将变量生命为可空值类型:

int i = null; //非法
int? i = null; //合法

可空类型的属性:

int? i = null;
...
if(!i.HasValus)
{
    i = 99;
}
else
{
    Console.WriteLine(i.Value);
}

ref:

static void example(ref int a)
{
    a++;
}
static void Main()
{
    int arg = 42;
    example(ref arg);
    //arg=43
}

out:

static void example(out int a)
{
    a = 42;
}
static void Main()
{
    int arg;
    example(out arg);
    //arg=42
}

object:

Circle c;
c = new Circle(42);
object o;
o = c;

创建和管理类和对象 – 第七章 – C# 从入门到放弃

创建构造器的一个例子:

class Circle
{
    private int radius;
    
    public Circle()  //默认构造器
    {
        radius = 0;
    }
    public Circle(int initalRadius)  //重载的构造器
    {
        radius = initialRadius;
    }
    public double Area()
    {
        return Math.PI * radius * radius;
    }
}

使用多文件时的写法:

Circ1.cs内容:

partial class Circle
{
    public Circle()  //默认构造器
    {
        radius = 0;
    }
    public Circle(int initalRadius)  //重载的构造器
    {
        radius = initialRadius;
    }
}

Circ2.cs内容:

partial class Circle
{
    private int radius;
    public double Area()
    {
        return Math.PI * radius * radius;
    }
}

调用自己的字段时,使用this关键字:

class Point
{
    private int x, y;
    private static int objectCount = 0;
    public Point()
    {
        this.x = -1;
        this.y = -1;
        objectCount++;
    }
    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
        objectCount++;
    }
    public double DistanceTo(Point other)
    {
        int xDiff = this.x - other.x;   //注意此处
        int yDiff = this.y - other.y;
        double distance = Math.Sqrt((xDiff * xDiff) + (yDiff * yDiff));
        return distance;
    }
    public static int ObjectCount() => objectCount;
    //ObjectCount方法返回objectCount的值
}

=======

静态方法/数据使用static标记

只能访问标记为static的其他方法和字段

静态类(不允许被new:

class Math
{
    ...
    public const double PI = 3.14159265358979;
}

匿名类:

var myxxxx = new {Name = "xx", Age = 123};
Console.WriteLine($"Name:{myxxxx.Name},Age:{myxxxx.Age}");


var myyyyy = new {Name = "yy", Age = 321};

myxxxx = myyyyy; //合法,因为具有相同类型

异常处理 – 第六章 – C# 从入门到放弃

基本语法:

try
{
    ...
}
catch(Exception ex) when (ex.GetTypr() != typeof(System.OutOfMenoryException))
{
    ....
}

=====

数据溢出异常的处理:

checked:

int number = int.MaxValue;
checked
{
    int willThrow = number++;
    Console.WriteLine("won't run to here");
}

unchecked:

int number = int.MaxValue;
unchecked
{
    int willThrow = number++;
    Console.WriteLine("will run to here");
}

also:

try
{
    int lhs = 9876543;
    int rhs = 9876543;
    int outcome = 0;
    outcome = checked(lhs * rhs);
}
catch(OverflowException oEx)
{
    result.Text = oex.Message;
}

=====

手动抛出异常:

try
{
    throw new ArgumentOutOfRangeException("error!");
}
catch(ArgumentOutOfRangeException msg)
{
    xxx.Text = msg.Message;
}

finally的用法:

try
{
    DataConnection.Open();
    DataCommand.ExecuteReader();
    ...
    return;
}
finally
{
    DataConnection.Close();
}
//无论是否抛出异常,也无论从什么地方 return 返回,finally 语句块总是会执行,这样你有机会调用 Close 来关闭数据库连接(即使未打开或打开失败,关闭操作永远是可以执行的),以便于释放已经产生的连接,释放资源。 顺便说明,return 是可以放在 try 语句块中的。但不管在什么时机返回,在返回前,finally 将会执行。
//小结
try
{
    // 执行的代码,其中可能有异常。一旦发现异常,则立即跳到 catch 执行。否则不会执行 catch 里面的内容
}
catch
{
    // 除非 try 里面执行代码发生了异常,否则这里的代码不会执行
}
finally
{
    // 不管什么情况都会执行,包括 try catch 里面用了 return , 可以理解为只要执行了 try 或者 catch,就一定会执行 finally
}