C #에서 델리게이트를 어떻게 사용합니까?
C #에서 델리게이트를 어떻게 사용합니까?
답변:
이제 C #에 람다 식과 익명 메서드가 있으므로 대리자를 훨씬 더 많이 사용합니다. 논리를 구현하기 위해 항상 별도의 메서드가 있어야하는 C # 1에서는 대리자를 사용하는 것이 종종 의미가 없었습니다. 요즘에는 다음을 위해 대리자를 사용합니다.
대리인은 여러 목적에 매우 유용합니다.
이러한 목적 중 하나는 데이터 시퀀스를 필터링하는 데 사용하는 것입니다. 이 경우 하나의 인수를 받아들이고 대리자 자체의 구현에 따라 true 또는 false를 반환하는 조건 자 대리자를 사용합니다.
여기에 어리석은 예가 있습니다. 이것에서 좀 더 유용한 것을 외삽 할 수 있다고 확신합니다.
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<String> names = new List<String>
{
"Nicole Hare",
"Michael Hare",
"Joe Hare",
"Sammy Hare",
"George Washington",
};
// Here I am passing "inMyFamily" to the "Where" extension method
// on my List<String>. The C# compiler automatically creates
// a delegate instance for me.
IEnumerable<String> myFamily = names.Where(inMyFamily);
foreach (String name in myFamily)
Console.WriteLine(name);
}
static Boolean inMyFamily(String name)
{
return name.EndsWith("Hare");
}
}
static Boolean inMyFamily(String name)
방법 대리자이다. 델리게이트를 매개 변수로 취하는 곳. 델리게이트가되는에 메서드 이름을 전달할 때 델리게이트는 함수 포인터 일뿐 .Where(delegate)
입니다. inMyFamily는 부울 유형을 반환하므로 실제로는 술어로 간주됩니다. 술어는 부울을 반환하는 대리자 일뿐입니다.
또 다른 흥미로운 답변을 찾았습니다.
동료가 방금이 질문을했습니다. .NET에서 대리인의 요점은 무엇입니까? 내 대답은 매우 짧았고 그가 온라인에서 찾지 못한 것은 방법의 실행을 지연시키는 것이었다.
출처 : LosTechies
LINQ가하는 것처럼.
대리자를 사용하여 함수 유형 변수 및 매개 변수를 선언 할 수 있습니다.
예
"자원 차용"패턴을 고려하십시오. 클라이언트 코드가 그 사이에 리소스를 "차용"하도록 허용하면서 리소스 생성 및 정리를 제어하려고합니다.
이것은 대리자 형식을 선언합니다.
public delegate void DataReaderUser( System.Data.IDataReader dataReader );
이 서명과 일치하는 모든 메서드를 사용하여이 형식의 대리자를 인스턴스화 할 수 있습니다. C # 2.0에서는 메서드 이름을 사용하거나 익명 메서드를 사용하여 암시 적으로이 작업을 수행 할 수 있습니다.
이 메소드는 유형을 매개 변수로 사용합니다. 대리자의 호출을 확인합니다.
public class DataProvider
{
protected string _connectionString;
public DataProvider( string psConnectionString )
{
_connectionString = psConnectionString;
}
public void UseReader( string psSELECT, DataReaderUser readerUser )
{
using ( SqlConnection connection = new SqlConnection( _connectionString ) )
try
{
SqlCommand command = new SqlCommand( psSELECT, connection );
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while ( reader.Read() )
readerUser( reader ); // the delegate is invoked
}
catch ( System.Exception ex )
{
// handle exception
throw ex;
}
}
}
다음과 같이 익명 메서드로 함수를 호출 할 수 있습니다. 익명 메소드는 변수를 사용할 수 있습니다 선언 외부 자체. 이것은 매우 편리합니다 (예제가 약간 인위적이긴하지만).
string sTableName = "test";
string sQuery = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" + sTableName + "'";
DataProvider.UseReader( sQuery,
delegate( System.Data.IDataReader reader )
{
Console.WriteLine( sTableName + "." + reader[0] );
} );
델리게이트는 종종 하나의 방법으로 인터페이스 대신 사용될 수 있습니다. 일반적인 예로 관찰자 패턴이 있습니다. 다른 언어에서는 어떤 일이 발생했다는 알림을 받으려면 다음과 같이 정의 할 수 있습니다.
class IObserver{ void Notify(...); }
C #에서는 핸들러가 대리자 인 이벤트를 사용하여 더 일반적으로 표현됩니다. 예를 들면 다음과 같습니다.
myObject.SomeEvent += delegate{ Console.WriteLine("..."); };
예를 들어 목록에서 항목 집합을 선택하는 경우와 같이 조건자를 함수에 전달해야하는 경우 대리자를 사용하는 또 다른 좋은 장소 :
myList.Where(i => i > 10);
위는 다음과 같이 작성할 수도있는 람다 구문의 예입니다.
myList.Where(delegate(int i){ return i > 10; });
대리자를 사용하는 것이 유용 할 수있는 또 다른 곳은 공장 함수를 등록하는 것입니다. 예를 들면 다음과 같습니다.
myFactory.RegisterFactory(Widgets.Foo, () => new FooWidget());
var widget = myFactory.BuildWidget(Widgets.Foo);
이게 도움이 되길 바란다!
나는 이것에 대해 정말 늦게 들어 왔지만 오늘 델리게이트의 목적을 파악하는 데 어려움을 겪었고 그들의 목적을 잘 설명하는 동일한 결과를 제공하는 두 개의 간단한 프로그램을 작성했습니다.
NoDelegates.cs
using System;
public class Test {
public const int MAX_VALUE = 255;
public const int MIN_VALUE = 10;
public static void checkInt(int a) {
Console.Write("checkInt result of {0}: ", a);
if (a < MAX_VALUE && a > MIN_VALUE)
Console.WriteLine("max and min value is valid");
else
Console.WriteLine("max and min value is not valid");
}
public static void checkMax(int a) {
Console.Write("checkMax result of {0}: ", a);
if (a < MAX_VALUE)
Console.WriteLine("max value is valid");
else
Console.WriteLine("max value is not valid");
}
public static void checkMin(int a) {
Console.Write("checkMin result of {0}: ", a);
if (a > MIN_VALUE)
Console.WriteLine("min value is valid");
else
Console.WriteLine("min value is not valid");
Console.WriteLine("");
}
}
public class Driver {
public static void Main(string [] args) {
Test.checkInt(1);
Test.checkMax(1);
Test.checkMin(1);
Test.checkInt(10);
Test.checkMax(10);
Test.checkMin(10);
Test.checkInt(20);
Test.checkMax(20);
Test.checkMin(20);
Test.checkInt(30);
Test.checkMax(30);
Test.checkMin(30);
Test.checkInt(254);
Test.checkMax(254);
Test.checkMin(254);
Test.checkInt(255);
Test.checkMax(255);
Test.checkMin(255);
Test.checkInt(256);
Test.checkMax(256);
Test.checkMin(256);
}
}
Delegates.cs
using System;
public delegate void Valid(int a);
public class Test {
public const int MAX_VALUE = 255;
public const int MIN_VALUE = 10;
public static void checkInt(int a) {
Console.Write("checkInt result of {0}: ", a);
if (a < MAX_VALUE && a > MIN_VALUE)
Console.WriteLine("max and min value is valid");
else
Console.WriteLine("max and min value is not valid");
}
public static void checkMax(int a) {
Console.Write("checkMax result of {0}: ", a);
if (a < MAX_VALUE)
Console.WriteLine("max value is valid");
else
Console.WriteLine("max value is not valid");
}
public static void checkMin(int a) {
Console.Write("checkMin result of {0}: ", a);
if (a > MIN_VALUE)
Console.WriteLine("min value is valid");
else
Console.WriteLine("min value is not valid");
Console.WriteLine("");
}
}
public class Driver {
public static void Main(string [] args) {
Valid v1 = new Valid(Test.checkInt);
v1 += new Valid(Test.checkMax);
v1 += new Valid(Test.checkMin);
v1(1);
v1(10);
v1(20);
v1(30);
v1(254);
v1(255);
v1(256);
}
}
약간 다른 용도는 반사 속도를 높이는 것입니다. 즉, 매번 리플렉션을 사용하는 대신 Delegate.CreateDelegate
메서드 (a MethodInfo
)에 대한 (형식화 된) 대리자를 만들고 대신 해당 대리자를 호출하는 데 사용할 수 있습니다 . 이것은 다음입니다 많은 검사가 이미 수행 된 것처럼, 빨리 호출 당.
를 사용하면 Expression
동일한 작업을 수행하여 즉석에서 코드를 만들 수도 있습니다. 예를 들어 Expression
런타임에 선택한 유형에 대한 + 연산자를 나타내는를 쉽게 만들 수 있습니다 (언어가 제공하지 않는 제네릭에 대한 연산자 지원을 제공하기 위해). ; 를 Expression
형식화 된 델리게이트로 컴파일 할 수 있습니다 .
대리자를 사용하여 스레드와 통신합니다.
예를 들어 파일을 다운로드하는 Win Forms 앱이있을 수 있습니다. 앱은 다운로드를 수행하기 위해 작업자 스레드를 시작합니다 (GUI가 잠기는 것을 방지 함). 작업자 스레드는 델리게이트를 사용하여 상태 메시지 (예 : 다운로드 진행률)를 주 프로그램으로 다시 보내므로 GUI가 상태 표시 줄을 업데이트 할 수 있습니다.
이벤트 핸들러 용
메서드 매개 변수에 메서드를 전달하려면
이벤트, 기타 anynch 작업
게으른 매개 변수 초기화! 모든 이전 답변 (전략 패턴, 관찰자 패턴 등) 외에도 델리게이트를 사용하면 매개 변수의 지연 초기화를 처리 할 수 있습니다. 예를 들어, 꽤 많은 시간이 걸리고 특정 DownloadedObject를 반환하는 함수 Download ()가 있다고 가정합니다. 이 개체는 특정 조건에 따라 저장소에서 사용됩니다. 일반적으로 다음을 수행합니다.
storage.Store(conditions, Download(item))
그러나 대리자 (보다 정확하게는 람다)를 사용하면 저장소의 서명을 변경하여 Condition 및 Func <Item, DownloadedObject>를 수신하고 다음과 같이 사용하여 다음을 수행 할 수 있습니다.
storage.Store(conditions, (item) => Download(item))
따라서 저장소는 필요한 경우에만 대리인을 평가하고 조건에 따라 다운로드를 실행합니다.
대표자 사용
In Array.Sort (T [] 배열, 비교 비교), List.Sort (Comparison 비교) 등의 비교 매개 변수
Delegate는 참조로 메서드를 호출하는 데 사용됩니다. 예를 들면 :
delegate void del_(int no1,int no2);
class Math
{
public static void add(int x,int y)
{
Console.WriteLine(x+y);
}
public static void sub(int x,int y)
{
Console.WriteLine(x-y);
}
}
class Program
{
static void Main(string[] args)
{
del_ d1 = new del_(Math.add);
d1(10, 20);
del_ d2 = new del_(Math.sub);
d2(20, 10);
Console.ReadKey();
}
}