前言
最近在回顾C#有关基础内容(基于C#入门经典),记录一下学习过程以及学习的有关知识点总结和一些自己的理解。注释尽量通俗易懂理解,方便以后回来再回顾一下。有什么错误的地方,也请大家指正,也希望大家多多补充,比较适合初学者对概念的理解,希望对大家也有所帮助。
一、类成员的定义
在类的定义中,可以有***字段、方法和属性***三个成员。
每个成员都有自己的访问级别。用以下四个关键词来定义访问级别
(1)public——成员可由任何代码访问
(2)private——成员只能用类中的代码访问(如果没有使用任何关键词定义访问级别,那么就默认使用这个关键词)
(3)internel——成员只能由定义它的程序集(项目内部)的代码访问
(4)protected——成员只能由类或派生类中的代码访问。
注意!
在NET.Framework中的公共字段、方法和属性三个成员一般采用PascalCasing形式命名。而私有的字段、方法和属性一般用camelCasing形式命名。
二、定义示例与注意问题
1.定义字段、方法、属性
代码如下(示例):
class MyClass
{
//定义字段
public int MyInt;
//定义方法 Lambda表达式在十三章中介绍
public string GetString () =>"here is a string."
//定义属性 属性与字段的区别:字段后面有分号,而属性后 面包含set与get代码块
public int MyIntProp
{
//get访问器
get
{
return myInt;
//获取属性的值代码
}
//set访问器
set
{
myInt = value;
//设置属性的值代码
}
}
}
2.定义字段需要注意的问题
(1)在定义字段时可以使用readonly关键词,表示这个字段只能在构造函数(第八章)的过程中赋值,或者由初始化赋值语句赋值。
(2)使用static来定义静态字段和使用const来创建一个常量。const常量也是静态的,但是不需要也不能再加static关键词来修饰。
代码如下(示例):
class MyClass
{
//定义字段使用readonly关键字
public readonly int MyInt = 17;
//定义静态字段必须通过定义他们的类来访问(MyClass.MyInt)而不能通过这个类的实例来访问
public static int MyInt;
}
3.定义方法需要注意的问题
在方法的定义中有时也可用的修饰关键词来修饰。
(1)virtual——表示该方法可以重写。
(2)abstract——表示该方法必须在非抽象的派生类重写,就必须使用该关键字。
(3)override——如果方法被重写,就必须使用该关键字。
(4)extern——该方法的定义放在其他地方,使用该关键词可在项目外部提供该方法的实现代码。
方法重写的示例代码如下(示例):
//基类
public class MyBaseClass
{
public virtual void DoSomething()
{
//方法实现代码
}
}
//派生类
public class MyDerivedClass: MyBaseClass
{
public override void DoSomething()
{
//派生类实现,重写基类实现
}
}
在使用override重写方法后,也可以使用sealed来指定在派生类中不能对该方法作进一步修改。即不能由派生类重写。
public class MyDerivedClass: MyBaseClass
{
public override sealed void DoSomething()
{
//派生类实现,重写基类实现
}
}
4.定义属性需要注意的问题
属性有两个访问器get与set,一般简单的属性需要和字段相关联,并且相互配合使用。如下代码所示。
//定义属性使用的字段
private int myInt;
//定义属性
public int MyIntProp
{
get{return myInt;}
set{myInt = value;}
}
//***? 可空运算符*** int myInt?默认为null,若是int myInt则默认为0
//***?? 空合并运算符*** 当value为null时返回,则返回0,不为null时返回value值本身
private int? myInt;
public int? MyIntProp
{
get{return myInt;}
set{myInt = value ?? 0;}
}
从上边的例子可以看出,上面的字段定义为是私有的,那么类外部的代码是无法访问该字段的,外部的代码只能通过属性来访问该字段。
还需要注意的是属性还可以使用virtual、override、abstract关键字如同方法一样,并且访问器还有自己的可访问性,例如
//定义属性使用的字段
private int myInt;
//定义属性
public int MyIntProp
{
get{return myInt;}
protected set{myInt = value;}
}
但是需要注意的是,访问器的访问修饰符取决于属性的可访问性,访问器的可访问性不能高于它属的属性。
4.举个例子
以下例子是字段、属性、方法的一个例子,注释比较多适合给初学者学习。该例子是基于控制台应用程序。
using System;
using static System.Console;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
WriteLine("Creating object myObj...");
//创建一个对象myObj实例,实例化这个类必须使用非默认的构造函数来进行,
//因为MyClass类的默认构造函数是私有的,
//readonly定义的字段在执行构造函数时进行赋值。
MyClass myObj = new MyClass("My Object");
WriteLine("myObj created");
for(int i =-1;i<=0;i++)
{
try
{
//$符号与string.format()作用基本相同
WriteLine($"\nAttempting to assign{i} to myObj.Val...");
//给MyClass类的实例化对象myObj的属性Val赋值
myObj.Val = i;
WriteLine($"Value {myObj.Val} assigned to mybj.Val...");
}
catch(Exception e)
{
WriteLine($"\nException {e.GetType ().FullName } thrown");
WriteLine ($"Message:\n\"{e.Message}\"");
}
}
WriteLine("\nOutputting myObj.ToString ()...");
//使用重写的ToString()方法输出一个格式化的字符串。
WriteLine(myObj .ToString ());
WriteLine("myObj.Tostring() Output");
WriteLine("\nmyDoubledIntProp=5...");
//将MyClass类中定义的只读属性输出
WriteLine($"Getting myDoubledIntProp of 5 is {myObj .MyDoubledIntProp} ");
ReadKey();
}
}
//创建MyClass类
public class MyClass
{
//readonly表示该字段只能在构造函数中赋值或在初始化赋值
public readonly string Name;
//定义私有字段
private int intVal;
//定义公共属性Val
public int Val
{
//获取属性值
get { return intVal; }
//设置属性值
set
{
//设置之前先做出判断
if (value >= 0 && value <= 10)
{
intVal = value;
}
//如果不符合条件抛出异常
else
throw (new ArgumentOutOfRangeException("Val", value, "Val must be assigned a value between 0 and 10."));
}
}
//重写ToString方法
public override string ToString() => "Name: "+Name +"\nVal: " + Val ;
//MyClass类私有的构造函数
private MyClass() : this("Default Name") { }
//MyClass类非私有的构造函数
public MyClass (string newName)
{
Name = newName;
intVal = 0;
}
//定义一个私有字段
private int myDoubledInt = 5;
//定义了一个基于表达式的属性,这个功能可以把属性的定义减少为一行代码。
//基于表达式的属性是用Lambda箭头后跟等式来定义
public int MyDoubledIntProp => (myDoubledInt * 2);
}
}
总结
以上内容是第十章的第一部分,介绍了类的成员字段、方法、属性,并分别介绍了定义和使用时他们的通常命名方式,和他们的可访问性,以及属于比较简单的概念,其中属性和方法在基类中可定义为抽象和虚拟的成员,以及一些其他注意事项,第二部分属于类的稍加复杂的概念,之后再做介绍。