1. 抽象類/方法
1.1 抽象類
通過在類定義前面放置關(guān)鍵字 abstract ,可以將類聲明為抽象類;抽象類不能實例化。
public abstract class A
{
// Class members here.
}
抽象類的用途是提供一個可供多個派生類共享的通用基類定義。
例如,類庫可以定義一個抽象類,將其用作多個類庫函數(shù)的參數(shù),并要求使用該庫的程序員通過創(chuàng)建派生類來提供自己的類實現(xiàn)。
1.2 抽象方法
抽象類也可以定義抽象方法。 方法是將關(guān)鍵字 abstract 添加到方法的返回類型的前面。
public abstract class A
{
public abstract void DoWork(int i);
}
抽象方法沒有實現(xiàn),所以方法定義后面是分號,而不是常規(guī)的方法塊。 抽象類的派生類必須實現(xiàn)所有抽象方法。 當抽象類從基類繼承虛方法時,抽象類可以使用抽象方法重寫該虛方法。
2. 密封類/方法
2.1 密封類
密封類是修飾為 sealed 的類,不能有子類;一般只有系統(tǒng)中的一些基本類聲明為密封類。
public sealed class SealedClass
{
}
2.2 密封方法
密封方法只能是在已經(jīng)被重寫的方法中定義,表示這個方法不可以再被重寫;
class BaseClass
{
public virtual void Move()
{
//...
}
}
class DerivedClass : BaseClass
{
public sealed override void Move() //只能在重寫的方法里定義sealed
{
base.Move();
}
}
密封類和密封方法的作用,是放置重寫某些類導致代碼的混亂,或者一些出于商業(yè)上的原因。
3. 靜態(tài)類/類成員
3.1 靜態(tài)類
靜態(tài)類基本上與非靜態(tài)類相同,但存在一個差異:靜態(tài)類無法實例化,不能繼承或被繼承;且只包含靜態(tài)成員;不能包含實例構(gòu)造函數(shù),但可以包含靜態(tài)構(gòu)造函數(shù),且不能對其構(gòu)造函數(shù)使用訪問修飾符。
public static class DemoStaticClass
{
public static string ReturnValue(string value)
{
return value;
}
}
3.3 靜態(tài)方法/字段
public class Automobile
{
public static int NumberOfWheels = 4;
public static void Drive() { }
}
4. 擴展方法
擴展方法使你能夠向現(xiàn)有類型“添加”方法,而無需創(chuàng)建新的派生類型、重新編譯或以其他方式修改原始類型,現(xiàn)有類型既可以是 int ,string 等數(shù)據(jù)類型,也可以是自定義的數(shù)據(jù)類型。
擴展方法是一種特殊的靜態(tài)方法,但可以像擴展類型上的實例方法一樣進行調(diào)用,調(diào)用擴展方法與調(diào)用在類型中實際定義的方法之間沒有明顯的差異。
擴展方法的第一個參數(shù)指定該方法作用于哪個類型,并且該參數(shù)以 this 修飾符為前綴。 擴展方法當然不能破壞面向?qū)ο蠓庋b的概念,所以只能是訪問所擴展類的 public 成員。
擴展方法最終其實還是被編譯器處理為普通靜態(tài)方法的調(diào)用,本質(zhì)上還是靜態(tài)方法的調(diào)用,所不能訪問類的外部成員。
4.1 一般擴展方法
必要條件
- 擴展方法所在的類必須為靜態(tài)類
- 擴展方法必須為靜態(tài)方法
- 第一個參數(shù)必須為需要擴展的類型且以
this 為前綴
代碼實現(xiàn)
public class Person
{
public string Name { set; get; }
public int Age { set; get; }
}
public static class MyExtensions
{
#region 基本類型擴展方法
public static int GetLength(this String value)
{
return value.Length;
}
public static int GetCount(this string value,int len)
{
return value.Length + len;
}
#endregion
#region 自定義類型擴展方法
public static bool GetBIsChild(this Person oPerson)
{
if (oPerson.Age >= 18)
return false;
else
return true;
}
#endregion
}
使用擴展方法
int len = "李白".GetLength();
int count = "李白".GetCount(2);
var oPerson1 = new Person();
oPerson1.Age = 20;
var bIsChild = oPerson1.GetBIsChild();
4.2 泛型擴展方法
定義方法
public static class MyExtensions
{
public static bool ValIsNull<T>(this T val)
{
if (val == null) return false;
else return true;
}
public static IList<T> ForeachOne<T>(this IList<T> sources)
{
return sources;
}
}
使用方法
string value = "李白";
value.ValIsNull();
Cval cval = new Cval();
cval.ValIsNull();
List<string> str_list = new List<string>();
str_list.ForeachOne();
List<Cval> Cval_list = new List<Cval>();
Cval_list.ForeachOne();
4.3 泛型委托方法
聲明方法
public static class CustomExtensions
{
public static TSource Handle<TSource>(this TSource source, Func<TSource, bool> predicate)
{
if (predicate(source)) return source;
else return default(TSource);
}
public static List<TSource> MyWhere<TSource>(this List<TSource> source, Func<TSource, bool> predicate)
{
List<TSource> list = new List<TSource>();
foreach (var item in source)
{
if (predicate(item)) list.Add(item);
}
return list;
}
static Func<TSource, bool> CombinePredicates<TSource>(Func<TSource, bool> predicate1, Func<TSource, bool> predicate2)
{
return x => predicate1(x) && predicate2(x);
}
}
使用方法
class Program
{
static void Main(string[] args)
{
string value_isnull = "李白".Handle(x => x != null);
Console.WriteLine(value_isnull);
string value_len = "李白".Handle(x => x.Length > 6);
Console.WriteLine(value_len);
List<string> list = new List<string> { "1", "12" };
var new_list = list.MyWhere(x => x.Length > 1);
foreach (var item in new_list)
{
Console.WriteLine(item);
}
}
}
5. 深/淺拷貝
說明:深拷貝和淺拷貝只是拷貝的兩種現(xiàn)象(實現(xiàn)),不是技術(shù)。
5.1 兩者區(qū)別
? 淺拷貝是指將對象中的數(shù)值類型的字段拷貝到新的對象中,而對象中的引用型字段則指復制它的一個引用到目標對象。如果改變目標對象中引用型字段的值他將反映在原始對象中,也就是說原始對象中對應的字段也會發(fā)生變化。
? 深拷貝與淺拷貝不同的是對于引用的處理,深拷貝將會在新對象中創(chuàng)建一個新的和原始對象中對應字段相同(內(nèi)容相同)的字段,也就是說這個引用和原始對象的引用是不同的,我們在改變新對象中的這個字段的時候是不會影響到原始對象中對應字段的內(nèi)容。
示例代碼
Cval cval = new Cval();
cval.num = 1;
Person person1 = new Person();
person1.Age = 1;
person1.cv = cval;
Person person2 = new Person();
person2.Age = person1.Age;
person2.cv = person1.cv;
person1.Age = 10;
person1.cv.num = 10;
Console.WriteLine($"person1:{person1.Age}-{person1.cv.num}");
Console.WriteLine($"person2:{person2.Age}-{person2.cv.num}");
示例結(jié)果
person1:10-10
person2:1-10
6. Action回調(diào)方法
6.1 基本使用
定義回調(diào)
public class Helper
{
public void Show(string value, Action<string> callBack)
{
callBack("姓名:" + value);
}
public void ShowTwo(string value, int age, Action<string, int> callBack)
{
callBack("姓名:" + value, age + 1);
}
}
使用回調(diào)
static void Main(string[] args)
{
Helper helper = new Helper();
helper.Show("李白", val => Console.WriteLine(val));
helper.ShowTwo("李白", 15, (val, age) => Console.WriteLine($"{val},{age}"));
}
|