CLR Via C# 버전 3 노트(24) - 위임
30064 단어 C#
주요 내용:
1. 위탁 본질
위탁의 본질은 하나의 종류이다. 기본적으로 종류를 정의할 수 있는 곳에서 위탁을 정의할 수 있다. C#에서 위탁한 문법은 사실 C#의 문법사탕일 뿐이다.
다음과 같은 의뢰를 정의합니다.
using System;
namespace delegate_test
{
internal delegate int Sum(int a, int b);
}
ILSpy를 사용하면 다음과 같은 IL 코드를 확인할 수 있습니다.
.class private auto ansi sealed delegate_test.Sum
extends [mscorlib]System.MulticastDelegate
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor (
object 'object',
native int 'method'
) runtime managed
{
} // end of method Sum::.ctor
.method public hidebysig newslot virtual
instance int32 Invoke (
int32 a,
int32 b
) runtime managed
{
} // end of method Sum::Invoke
.method public hidebysig newslot virtual
instance class [mscorlib]System.IAsyncResult BeginInvoke (
int32 a,
int32 b,
class [mscorlib]System.AsyncCallback callback,
object 'object'
) runtime managed
{
} // end of method Sum::BeginInvoke
.method public hidebysig newslot virtual
instance int32 EndInvoke (
class [mscorlib]System.IAsyncResult result
) runtime managed
{
} // end of method Sum::EndInvoke
} // end of class delegate_test.Sum
그중에서 우리는 알 수 있다
의뢰의 종류를 더욱 잘 이해하기 위해 다음은 간단한 예를 써서 의뢰의 구조 함수를 알아보자.
using System;
namespace delegate_test
{
internal delegate int Sum(int a, int b);
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
// , IL
// IL Sum 2 ( object , native int )
/*
.method public hidebysig specialname rtspecialname
instance void .ctor (
object 'object',
native int 'method'
) runtime managed
{
} // end of method Sum::.ctor
*/
Sum s = new Sum(Add);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static int Add(int a, int b)
{
return a+b;
}
}
}
코드에 대한 설명을 참고하십시오. C#에서 실례화된 의뢰의 작성법이 IL에서 본 의뢰의 구조 함수와 일치하지 않음을 알 수 있습니다.
사실 이것은 C#의 문법 사탕일 뿐입니다. 코드 작성을 편리하게 하기 위해 위의 코드를 컴파일한 후 ILSpy로 IL 코드를 보십시오.
IL_0000: nop
IL_0001: ldstr "Hello World!"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldnull
IL_000d: ldftn int32 delegate_test.Program::Add(int32, int32)
IL_0013: newobj instance void delegate_test.Sum::.ctor(object, native int)
우리는 실제 운행할 때 의뢰한 구조 함수, 하나는null, 그리고 하나는함수Add의 주소를 구성하는 것을 발견했다.
여기 있는 첫 번째 인자 object가null인 이유는, Add 함수는static이기 때문에, 하나의 object를 실례화하지 않아도 된다.
다음은 static이 아닌 함수 Add2를 만들어서 Object의 값이null인지 확인합니다.
using System;
namespace delegate_test
{
internal delegate int Sum(int a, int b);
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
// , IL
// IL Sum 2 ( object , native int )
/*
.method public hidebysig specialname rtspecialname
instance void .ctor (
object 'object',
native int 'method'
) runtime managed
{
} // end of method Sum::.ctor
*/
Sum s = new Sum(Add);
// static Add2
Sum s2 = new Sum((new Program()).Add2);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static int Add(int a, int b)
{
return a+b;
}
public int Add2(int a, int b)
{
return a+b;
}
}
}
Sum s2 = new Sum((new Program()).Add2); IL은 다음과 같습니다.
IL_0019: newobj instance void delegate_test.Program::.ctor()
IL_001e: ldftn instance int32 delegate_test.Program::Add2(int32, int32)
IL_0024: newobj instance void delegate_test.Sum::.ctor(object, native int)
위탁의 Invoke 함수는 우리가 실제 위탁을 실행할 때 호출하는 함수이며, Begin Invoke와 End Invoke는 비동기적인 상황에 사용된다.
using System;
namespace delegate_test
{
internal delegate int Sum(int a, int b);
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
// , IL
// IL Sum 2 ( object , native int )
/*
.method public hidebysig specialname rtspecialname
instance void .ctor (
object 'object',
native int 'method'
) runtime managed
{
} // end of method Sum::.ctor
*/
Sum s = new Sum(Add);
Sum s2 = new Sum((new Program()).Add2);
// s(5,7) Invoke
Console.WriteLine("5+7="+ s(5,7));
// ,
Console.WriteLine("5+7="+ s.Invoke(5,7));
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static int Add(int a, int b)
{
return a+b;
}
public int Add2(int a, int b)
{
return a+b;
}
}
}
s(5,7)는 s.Invoke(5,7)의 간소화 문법이다.
2. 의뢰 체인
의뢰는 리셋 함수에 사용되는 이상 한 번에 여러 함수를 리셋하여 하나의 의뢰 체인을 형성할 수 있어야 한다.
이 의뢰 체인에는 리셋 함수를 동적으로 추가하고 줄일 수 있을 것이다.
실험 코드는 다음과 같습니다.
using System;
namespace delegate_test
{
internal delegate void Print_Sum(int a, int b);
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Print_Sum s = null;
Print_Sum s1 = new Print_Sum(Add1);
Print_Sum s2 = new Print_Sum((new Program()).Add2);
Print_Sum s3 = new Print_Sum((new Program()).Add3);
s += s1;
s += s2;
s += s3;
s(1,2);
// Add2
s -= s2;
s(1,2);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static void Add1(int a, int b)
{
Console.WriteLine("function Add1.... result is " + (a+b).ToString());
}
public void Add2(int a, int b)
{
Console.WriteLine("function Add2.... result is " + (2*(a+b)).ToString());
}
public void Add3(int a, int b)
{
Console.WriteLine("function Add3.... result is " + (3*(a+b)).ToString());
}
}
}
운행의 결과도 예상과 일치하지만 사실 그 중의 s+=s1;s-=s2;또한 C#의 문법 사탕으로 실제 사용되는 것은 시스템이다.Delegate의 Combine 메서드 및 Remove 메서드
관심 있으면 컴파일된 IL 코드를 보십시오.
3. 동적 의뢰
동적 의뢰는 사실 많이 사용되지 않고 반사와 결합하여 사용된다.호출된 의뢰가 정의한 매개 변수의 개수와 매개 변수의 유형을 확정할 수 없을 때만 동적 의뢰가 필요합니다.
동적 의뢰를 사용하는 것은 주로 의뢰 실례를 생성하는 Create Delegate 방법과 의뢰를 호출하는 Dynamic Invoke 방법을 사용한다.
using System;
using System.Reflection;
internal delegate void print_sum(int a, int b);
internal delegate void print_string(string a);
public class Dynamic_Delegate
{
public static void Main(string[] args)
{
// delegate , , args 。
// Main
// print_sum :
// delegate_test.exe print_sum Sum 2 3
// print_string :
// delegate_test.exe print_string Str "hello delegate!"
//
string delegate_name = args[0];
string method_name = args[1];
// 2 , ,
object[] method_args = new object[args.Length - 2];
for (int i = 0; i<args.Length-2; i++)
{
// print_sum int
if (delegate_name.Equals("print_sum"))
method_args[i] = int.Parse(args[2+i]);
else
method_args[i] = args[2+i];
}
//
Type delegate_type = Type.GetType(delegate_name);
//
MethodInfo mi = typeof(Dynamic_Delegate).GetMethod(method_name, BindingFlags.NonPublic | BindingFlags.Static);
// delegate
Delegate d = Delegate.CreateDelegate(delegate_type, mi);
//
d.DynamicInvoke(method_args);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
private static void Sum(int a, int b)
{
Console.WriteLine("delegate print_sum....... result is : " + (a+b).ToString());
}
private static void Str(string a)
{
Console.WriteLine("delegate print_string.... result is : " + a);
}
}
컴파일된 프로그램 집합 (내 프로그램 집합 이름은 delegate test.exe) 에 따라 명령줄에 각각 다음 명령을 입력하여 다른 delegate를 호출합니다.
delegate_test.exe print_sum Sum 2 3
delegate_test.exe print_string Str "hello delegate!"
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
WebView2를 Visual Studio 2017 Express에서 사용할 수 있을 때까지Evergreen .Net Framework SDK 4.8 VisualStudio2017에서 NuGet을 사용하기 때문에 패키지 관리 방법을 packages.config 대신 PackageReference를 사용해야...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.