C#入門詳細(10)
依頼とは
委任は関数ポインタのアップグレード版です
例:C/C++の関数ポインタ
すべてアドレス
変数(データ)は、莫個のアドレスを起点とするメモリに格納された値です.
関数(アルゴリズム)は、モジュールアドレスが7点のメモリに格納されたマシン言語命令のセットである
ダイレクトコールと間接コール
直接呼び出し:関数名で関数を呼び出し、CPUは関数名で直接関数の所在するアドレスを取得して実行を開始します.
間接呼び出し:関数ポインタで関数を呼び出し、CPUは関数ポインタに格納されている値を読み出して関数の所在地を取得し、実行を開始する.
依頼の簡単な使用
アクション依頼
Func依頼
委任された宣言
依頼は一種、クラスはデータ型なので、依頼も一種のデータ型です
一般的なクラスとは異なり、主に可読性を配慮するために宣言されています.
注意依頼の場所の宣言
書き間違えた場所の結果がネストされたタイプとして宣言されるのを避ける
パッケージされたメソッドとの互換性を委任
戻り値のデータ型が一致する
パラメータリストは、個数とデータ型が一致しています(パラメータ名は同じではありません)
使用依頼
例:メソッドをパラメータとして別のメソッドに渡す
1:テンプレートメソッドを正しく使用:指定した外部メソッドを使用して結果を生成
空欄の問題に相当する
常にコードの中央に配置
依頼に戻り値がある
正しい使用2:コールバックメソッド:作成した外部メソッドを呼び出す
パイプラインに相当
常にコードの末尾にある
依頼に戻り値がありません
注意:使いこなせない+使いやすい+機能が強いものは、悪用されると大変なことになります
欠点1:これは方法レベルの緊密な結合であり、現実の仕事では慎重にしなければならない.
欠点2:可読性を低下させ、debugの難易度を増加させる
欠点3:依頼コールバック,非同期呼び出し,マルチスレッドを絡み合わせることで,コードの読み取りとメンテナンスが困難になる
欠点4:委託使用が不適切であるとメモリの漏洩やプログラム性能の低下を招く可能性がある
インスタンスコード
テンプレートの方法:
3つのクラスを宣言します.それぞれ製品クラス、箱クラス、包装クラスです.
製品工場クラスを宣言し、包装箱クラスのFuncタイプ委託を実現
プロダクトファクトリクラスを直接呼び出す方法
コールバック方法:
ログクラスを追加
プロダクトファクトリにaction委任タイプパラメータを追加する
よびだし
委任された高度な使用
マルチキャスト依頼
パッケージング方法の前後順に
暗黙的非同期呼び出し
基本概念:
同期:昨日終わったら続けてやる
非同期:同時に
実行するプログラムごとに1つのプロセス
プロセスごとに複数のスレッドを持つことができます
差異:
同期呼び出しはスレッドの下にあります
非同期呼び出しのメカニズムは、複数のスレッドの下で
シリアル-同期-単一スレッドパラレル-非同期-マルチスレッド
暗黙的マルチスレッド/マルチスレッドの表示
ダイレクト同期呼び出しちょくせつどうきよびだし:メソッド名の使用ほうほうしきめいのしよう
間接同期呼び出し:ユニキャスト/マルチキャスト依頼invokeメソッドを使用する
暗黙非同期呼び出し:BeginInvokeメソッドを使用する
非同期コールの表示:ThreadまたはTaskの使用
ダイレクト同期呼び出しコード:
間接同期呼び出しコード:
ダイレクト同期呼び出しと間接同期呼び出しの効果は同じです.
暗黙的非同期呼び出しBeginInvoke()メソッドの使用
表示される非同期呼び出しは、ThreadオブジェクトまたはTaskオブジェクトを使用します.
依頼の使用に代わるインタフェースを適時に使用すべきである.
転載先:https://www.cnblogs.com/jingjingweixiao/p/11001146.html
委任は関数ポインタのアップグレード版です
例:C/C++の関数ポインタ
すべてアドレス
変数(データ)は、莫個のアドレスを起点とするメモリに格納された値です.
関数(アルゴリズム)は、モジュールアドレスが7点のメモリに格納されたマシン言語命令のセットである
ダイレクトコールと間接コール
直接呼び出し:関数名で関数を呼び出し、CPUは関数名で直接関数の所在するアドレスを取得して実行を開始します.
間接呼び出し:関数ポインタで関数を呼び出し、CPUは関数ポインタに格納されている値を読み出して関数の所在地を取得し、実行を開始する.
依頼の簡単な使用
アクション依頼
Func依頼
委任された宣言
依頼は一種、クラスはデータ型なので、依頼も一種のデータ型です
一般的なクラスとは異なり、主に可読性を配慮するために宣言されています.
注意依頼の場所の宣言
書き間違えた場所の結果がネストされたタイプとして宣言されるのを避ける
パッケージされたメソッドとの互換性を委任
戻り値のデータ型が一致する
パラメータリストは、個数とデータ型が一致しています(パラメータ名は同じではありません)
使用依頼
例:メソッドをパラメータとして別のメソッドに渡す
1:テンプレートメソッドを正しく使用:指定した外部メソッドを使用して結果を生成
空欄の問題に相当する
常にコードの中央に配置
依頼に戻り値がある
正しい使用2:コールバックメソッド:作成した外部メソッドを呼び出す
パイプラインに相当
常にコードの末尾にある
依頼に戻り値がありません
注意:使いこなせない+使いやすい+機能が強いものは、悪用されると大変なことになります
欠点1:これは方法レベルの緊密な結合であり、現実の仕事では慎重にしなければならない.
欠点2:可読性を低下させ、debugの難易度を増加させる
欠点3:依頼コールバック,非同期呼び出し,マルチスレッドを絡み合わせることで,コードの読み取りとメンテナンスが困難になる
欠点4:委託使用が不適切であるとメモリの漏洩やプログラム性能の低下を招く可能性がある
インスタンスコード
テンプレートの方法:
3つのクラスを宣言します.それぞれ製品クラス、箱クラス、包装クラスです.
class Product
{
public string Name { get; set; }
}
class Box
{
public Product Product { get; set; }
}
class WarpBox
{
public Box GetProduct(Func func)
{
Box box = new Box();
box.Product = func.Invoke();
return box;
}
}
製品工場クラスを宣言し、包装箱クラスのFuncタイプ委託を実現
class ProductFactory
{
public Product MakePizaa()
{
Product product = new Product();
product.Name = "Pizaa";
return product;
}
public Product MakeToyCar()
{
Product product = new Product();
product.Name = "ToyCar";
return product;
}
}
プロダクトファクトリクラスを直接呼び出す方法
static void Main(string[] args)
{
ProductFactory factory = new ProductFactory();
WarpBox warpbox = new WarpBox();
Box box1 = warpbox.GetProduct(factory.MakePizaa);
Box box2 = warpbox.GetProduct(factory.MakeToyCar);
Product product1 = box1.Product;
Product product2 = box2.Product;
Console.WriteLine(product1.Name);
Console.WriteLine(product2.Name);
Console.ReadLine();
}
コールバック方法:
ログクラスを追加
class Logger
{
public void MakeLog(Product product)
{
Console.WriteLine(string.Format(" {0}, {1}, {2}", product.Name, product.Price,DateTime.UtcNow));
}
}
プロダクトファクトリにaction委任タイプパラメータを追加する
class WarpBox
{
public Box GetProduct(Func func,Action action)
{
Box box = new Box();
box.Product = func.Invoke();
if (box.Product.Price>=50)
{
action.Invoke(box.Product);
}
return box;
}
}
よびだし
static void Main(string[] args)
{
ProductFactory factory = new ProductFactory();
WarpBox warpbox = new WarpBox();
Logger logger = new Logger();
Box box1 = warpbox.GetProduct(factory.MakePizaa,logger.MakeLog);
Box box2 = warpbox.GetProduct(factory.MakeToyCar,logger.MakeLog);
Product product1 = box1.Product;
Product product2 = box2.Product;
Console.WriteLine(product1.Name);
Console.WriteLine(product2.Name);
Console.ReadLine();
}
委任された高度な使用
マルチキャスト依頼
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student { Id = 1, PenColor = ConsoleColor.Cyan };
Student stu2 = new Student { Id = 2, PenColor = ConsoleColor.Red };
Student stu3 = new Student { Id = 3, PenColor = ConsoleColor.Yellow };
Action action1 = new Action(stu1.DoHomeWork);
Action action2 = new Action(stu2.DoHomeWork);
Action action3 = new Action(stu3.DoHomeWork);
action1 += action2;
action1 += action3;
action1.Invoke();
}
}
class Student
{
public int Id { get; set; }
public ConsoleColor PenColor { get; set; }
public void DoHomeWork()
{
for (int i = 0; i < 4; i++)
{
Console.ForegroundColor = this.PenColor;
Console.WriteLine(string.Format("{0} do homework", this.Id));
Thread.Sleep(1000);
}
}
}
パッケージング方法の前後順に
暗黙的非同期呼び出し
基本概念:
同期:昨日終わったら続けてやる
非同期:同時に
実行するプログラムごとに1つのプロセス
プロセスごとに複数のスレッドを持つことができます
差異:
同期呼び出しはスレッドの下にあります
非同期呼び出しのメカニズムは、複数のスレッドの下で
シリアル-同期-単一スレッドパラレル-非同期-マルチスレッド
暗黙的マルチスレッド/マルチスレッドの表示
ダイレクト同期呼び出しちょくせつどうきよびだし:メソッド名の使用ほうほうしきめいのしよう
間接同期呼び出し:ユニキャスト/マルチキャスト依頼invokeメソッドを使用する
暗黙非同期呼び出し:BeginInvokeメソッドを使用する
非同期コールの表示:ThreadまたはTaskの使用
ダイレクト同期呼び出しコード:
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student { Id = 1, PenColor = ConsoleColor.Cyan };
Student stu2 = new Student { Id = 2, PenColor = ConsoleColor.Red };
Student stu3 = new Student { Id = 3, PenColor = ConsoleColor.Yellow };
stu1.DoHomeWork();
stu2.DoHomeWork();
stu3.DoHomeWork();
for (int i = 0; i < 5; i++)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("Main thread is working");
}
}
}
class Student
{
public int Id { get; set; }
public ConsoleColor PenColor { get; set; }
public void DoHomeWork()
{
for (int i = 0; i < 4; i++)
{
Console.ForegroundColor = this.PenColor;
Console.WriteLine(string.Format("{0} do homework", this.Id));
Thread.Sleep(1000);
}
}
}
間接同期呼び出しコード:
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student { Id = 1, PenColor = ConsoleColor.Cyan };
Student stu2 = new Student { Id = 2, PenColor = ConsoleColor.Red };
Student stu3 = new Student { Id = 3, PenColor = ConsoleColor.Yellow };
Action action1 = new Action(stu1.DoHomeWork);
Action action2 = new Action(stu2.DoHomeWork);
Action action3 = new Action(stu3.DoHomeWork);
action1.Invoke();
action2.Invoke();
action3.Invoke();
for (int i = 0; i < 5; i++)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("Main thread is working");
}
}
}
class Student
{
public int Id { get; set; }
public ConsoleColor PenColor { get; set; }
public void DoHomeWork()
{
for (int i = 0; i < 4; i++)
{
Console.ForegroundColor = this.PenColor;
Console.WriteLine(string.Format("{0} do homework", this.Id));
Thread.Sleep(1000);
}
}
}
ダイレクト同期呼び出しと間接同期呼び出しの効果は同じです.
暗黙的非同期呼び出しBeginInvoke()メソッドの使用
表示される非同期呼び出しは、ThreadオブジェクトまたはTaskオブジェクトを使用します.
依頼の使用に代わるインタフェースを適時に使用すべきである.
転載先:https://www.cnblogs.com/jingjingweixiao/p/11001146.html