상세 c\#의뢰 체인
이전 주제다음 컴 파일 러 가 어떻게 번역 의뢰 를 하 는 지 소 개 했 습 니 다.중간 언어의 측면 에서 의뢰 를 보면 여러분 들 이 의뢰 를 더욱 이해 하 는 데 도움 을 줄 수 있 기 를 바 랍 니 다.그러나 예전 의 소 개 는 모두 의뢰 가 하나의 방법 일 뿐 입 니 다.그 의뢰 는 여러 가지 방법 을 포장 할 수 있 습 니까?생활 속 에서 자주 듣 기 때문에 제 가 여러분 의 의견 을 대표 하 는 등 이런 말 을 합 니 다.의뢰 도 대표 이기 때문에 그 가 한 사람 만 대표 할 수 있다 면 그의 매력 은 그리 크 지 않 을 것 입 니 다.그래서 우 리 는 여러 가지 방법 을 대표 할 수 있 는 지 를 의뢰 할 것 입 니 다.답 은 가능 합 니 다.이것 이 바로 본 주제 에서 말 하고 자 하 는 내용 입 니 다.의뢰 체인 도 하나의 의뢰 입 니 다.단지 여러 개의 의뢰 체인 을 함께 연결 하기 때문에 우 리 는 의뢰 체인 으로 그것 을 부 릅 니 다.
1.의뢰 체인 이란 무엇 인가
우 리 는 평소에 의뢰 대상 을 예화 할 때 한 가지 방법 을 연결 시 켰 다.앞의 주제 에 소 개 된 의뢰 도 하나의 방법 을 포장 했다.앞의 예 를 들 어 변호 사 를 위임 한 사람 은 한 사람 밖 에 없다.즉,당사자 가 한 사람 밖 에 없다 는 것 이다.그러나 현실 생활 에서 분명히 그렇지 않다.소송 을 할 때 변호 사 는 여러 가지 사건 을 동시에 맡 을 수 있다.또한 여러 명의 당시 사람들의 위임 을 받 아 이 변호 사 는 여러 당사자 와 연결 되 어 여러 당사자 의 사건 상황 을 알 아야 한다.사실은 이것 이 바로 생활 속 의 위탁 체인 이다.이때 이 변호 사 는 한 사람의 대표 변호사 가 아니 라 여러 명의 당사자 의 변호사 이다.생활 속 의 위탁 체인 은 C\#중의 위탁 체인 과 매우 유사 하 다.지금 C\#중의 위탁 체인 이 도대체 무엇 인지 말 해 보 자.
우선 의뢰 체인 은 하나의 의뢰 이기 때문에 의뢰 체인 의 느낌 이 어떤 C\#의 새로운 특성 인지 보지 마 세 요.그러나 여러 개의 의뢰 체인 을 한데 묶 으 려 면 여러 개의 의뢰 의 인용 을 저장 해 야 합 니 다.그러면 의뢰 체인 대상 은 어디에서 여러 개의 의뢰 의 인용 을 저장 합 니까?우리 가 지난 주제 에서 우리 가 소개 한 의뢰 유형 은 세 개의 비공 식 필드 가 있 는 것 을 기억 하 십 니까?이 세 필드 는― 이다.target,methodPtr 와invocationList,이 세 필드 가 무엇 을 대표 하 는 지 에 대해 서 는 제 지난 주제 의 글 을 볼 수 있 습 니 다.그러나invocationList 필드 는 여러 의뢰 인용 을 저장 하 는 곳 입 니 다.
더 잘 설명 하기 위해invocationList 는 의뢰 인용 을 어떻게 저장 하 는 지 다음 에 의뢰 체인 의 예 와 운영 결 과 를 본 다음 에 원인 을 분석 합 니 다.
using System;
namespace DelegateTest
{
public class Program
{
// ,
// int , void
public delegate void DelegateTest(int parm);
public static void Main(string[] args)
{
//
DelegateTest dtstatic = new DelegateTest(Program.method1);
//
DelegateTest dtinstance = new DelegateTest(new Program().method2);
//
dtstatic(1);
// Invoke
dtinstance.Invoke(1);
//
dtstatic(2);
// Invoke
dtinstance.Invoke(2);
Console.Read();
}
private static void method1(int parm)
{
Console.WriteLine(" , :" + parm);
}
private void method2(int parm)
{
Console.WriteLine(" , :" + parm);
}
}
}
실행 결과:왜 이런 결과 가 나 왔 는 지 분석 해 보 겠 습 니 다.
처음에 우 리 는 두 개의 위탁 변 수 를 실례 화 했 는데 다음 과 같은 코드 가 있다.
//
DelegateTest dtstatic = new DelegateTest(Program.method1);
//
DelegateTest dtinstance = new DelegateTest(new Program().method2);
의뢰 변수 dtstatic 과 dtinstance 가 인용 한 의뢰 대상 의 초기 상 태 는 다음 과 같 습 니 다.그 다음 에 저 희 는 의뢰 형식의 인용 변 수 를 정 의 했 습 니 다.delegatechain 은 처음에 의뢰 대상 이 없 었 고 빈 인용 이 었 습 니 다.아래 코드 를 실행 할 때...
delegatechain = (DelegateTest)Delegate.Combine(delegatechain, dtstatic);
Combine 방법 은 null 과 dtstatic 를 합병 하려 는 것 을 발 견 했 습 니 다.내부 에서 Combine 은 dtstatic 의 대상 으로 직접 돌아 갑 니 다.이때 delegatechain 과 dtstatic 변 수 는 모두 같은 의뢰 대상 을 참조 합 니 다.다음 그림 과 같 습 니 다.
이때 Combine 방법 은 delegatechain 이 의뢰 대상 을 인용 한 것 을 발견 했다.target 과methodPtr 필드 를 초기 화한 다음invocationList 필드 는 의뢰 대상 을 인용 한 배열 로 초기 화 되 었 습 니 다.이 배열 의 첫 번 째 요 소 는 method 1 방법 을 인용 한 의뢰 로 초기 화 되 었 습 니 다.배열 의 두 요 소 는 method 2 방법 을 인용 한 의뢰(즉 dtinstance 참조 의뢰 대상)로 초기 화 되 었 습 니 다.마지막 으로 delegaechain 은 새로 만 든 이 의뢰 대상 을 참조 하 는 것 으로 설정 되 었 습 니 다.다음은 그림 입 니 다.의뢰 체인 을 이해 하 는 데 도움 을 줄 수 있 습 니 다(멀티캐스트 의뢰 라 고도 합 니 다).
마찬가지 로 세 번 째 의뢰 체인 을 추가 하면 과정 도 위 와 같 습 니 다.이때 의뢰 대상 을 새로 만 듭 니 다.이때invocationList 필드 는 이 세 개의 의뢰 대상 배열 을 저장 하 는 것 을 참조 하 는 것 으로 초기 화 됩 니 다.그러나 누 군 가 는 의뢰 대상 의 의뢰 유형 변 수 를 Combine 방법 으로 호출 한 후 새로운 의뢰 대상 을 만 들 고 새로운 의뢰 대상 의 세 필드 를 다시 초기 화 합 니 다.마지막 으로 이전 의뢰 유형 변 수 를 새로 만 든 의뢰 대상(여기 서 의뢰 체인 의 생 성 과정 을 정리 해 드 립 니 다)을 참조 하면 이전 의뢰 대상 은 어떻게 합 니까?대부분의 사람들 이 이 의문 을 가지 고 있 을 것 이 라 고 믿 습 니 다.이 점 은 문자열 의 Concat 방법 과 비슷 합 니 다.이전 의뢰 대상 과--invocationList 필드 에서 인용 한 배열 은 쓰레기 로 회수 되 기 때 문 입 니 다.(그 렇 기 때문에 의뢰 는 문자열 String 과 마찬가지 로 변 하지 않 습 니 다.)
메모:다음 코드 를 호출 할 때 Delegate 의 Remove 방법 을 사용 하여 체인 에서 의뢰 를 삭제 할 수 있 습 니 다.
delegatechain =(DelegateTest)Delegate.Remove(delegatechain,new DelegateTest(method1));
Remove 방법 이 호출 될 때 delegateChain(첫 번 째 매개 변수)이 인용 한 의뢰 대상 내부 유 지 를 위 한 의뢰 배열 을 스 캔 합 니 다.delegateChain 이 인용 한 의뢰 대상 을 찾 으 면target 과methodPtr 필드
두 번 째 인자(새로 만 든 의뢰)의 필드 와 일치 하 는 의뢰 입 니 다.삭제 후 배열 에 하나의 데이터 항목 만 남 았 을 때 그 데이터 항목 을 되 돌려 줍 니 다.(의뢰 대상 을 새로 만 들 지 않 고 초기 화 합 니 다.이때 의invocationList 는 null 입 니 다.의뢰 대상 이 인용 한 배열 을 저장 하 는 것 이 아 닙 니 다.구체 적 으로 Remove 한 후 디 버 깅 할 수 있 습 니 다)이 때 배열 에 여러 개의 데이터 항목 이 남아 있다 면 의뢰 대상 을 새로 만 들 고 초기 화 합 니 다.invocationList 배열(이 때 배열 이 인용 한 의뢰 대상 이 하나 줄 었 습 니 다.Remove 방법 으로 삭 제 했 기 때 문 입 니 다).또한,매번 Remove 방법 이 호출 될 때마다 체인 에서 하나의 의뢰 만 삭제 할 수 있 고 일치 하 는 을 삭제 하지 않 습 니 다.target 과methodPtr 필드 의 모든 의뢰(이것 은 디 버 깅 할 수 있 습 니 다)
2.어떻게 의뢰 체인 중의 위탁 호출 을 통제 합 니까?
위 를 통 해 여러분 은 의뢰 체인 대상 을 어떻게 만 드 는 지 이해 할 수 있 을 것 이 라 고 믿 습 니 다.그러나 운영 결과 에서 알 수 있 듯 이 의뢰 체인 을 호출 할 때마다 의뢰 체인 포장 의 모든 방법 이 순서대로 실 행 됩 니 다.만약 에 의뢰 체인 에서 호출 된 의뢰 가 이상 을 던 지면 체인 중의 후속 모든 대상 이 호출 되 지 못 합 니 다.또한 의뢰 의 앞 에 void 가 아 닌 반환 형식 이 있다 면 마지막 반환 값 만 보류 되 고 다른 모든 반환 방법의 반환 값 은 버 려 집 니 다.이것 은 다른 모든 작업 의 반환 값 이 영원히 볼 수 없다 는 것 을 의미 합 니까?사실은 그렇지 않 습 니 다.저 희 는 Delegate.GetInvocationList 방법 으로 체인 의 모든 의뢰 를 표시 하고 자신의 정의 출력 을 추가 할 수 있 습 니 다.
GetInvocation List 방법 은 Delegate 참조 로 구 성 된 배열 을 되 돌려 줍 니 다.그 중에서 모든 배열 은 체인 의 의뢰 대상 을 가리 키 고 있 습 니 다.내부 에서 GetInvocationList 는 하나의 배열 을 만 들 고 초기 화 시 켜 데이터 의 모든 요소 가 체인 의 의뢰 를 참조 한 다음 이 배열 에 대한 인용 을 되 돌려 줍 니 다.하면,만약,만약...invocationList 필드 는 null 입 니 다.돌아 오 는 배열 은 하나의 요소 만 있 습 니 다.이 요 소 는 인 스 턴 스 자체 에 의뢰 하 는 것 입 니 다.다음은 프로그램 을 통 해 보 여 드 리 겠 습 니 다.
namespace DelegateChainDemo
{
class Program
{
// ,
// int , void
public delegate string DelegateTest();
static void Main(string[] args)
{
//
DelegateTest dtstatic = new DelegateTest(Program.method1);
//
DelegateTest dtinstance = new DelegateTest(new Program().method2);
DelegateTest dtinstance2 = new DelegateTest(new Program().method3);
// , null, ( , )
DelegateTest delegatechain = null;
delegatechain += dtstatic;
delegatechain += dtinstance;
delegatechain += dtinstance2;
////delegatechain =(DelegateTest)Delegate.Remove(delegatechain,new DelegateTest(method1));
////delegatechain = (DelegateTest)Delegate.Remove(delegatechain, new DelegateTest(new Program().method2));
Console.WriteLine(Test(delegatechain));
Console.Read();
}
private static string method1()
{
return " 1";
}
private string method2()
{
throw new Exception(" ");
}
private string method3()
{
return " 3";
}
//
private static string Test(DelegateTest chain)
{
if (chain == null)
{
return null;
}
//
StringBuilder returnstring = new StringBuilder();
// ,
Delegate[] delegatearray=chain.GetInvocationList();
//
foreach (DelegateTest t in delegatearray)
{
try
{
//
returnstring.Append(t() + Environment.NewLine);
}
catch (Exception e)
{
returnstring.AppendFormat(" {0} , :{1}{2}", t.Method.Name, e.Message, Environment.NewLine);
}
}
//
return returnstring.ToString();
}
}
}
실행 결과 캡 처:정리 하 다
본 주 제 는 의뢰 체인 을 만 드 는 방법 과 의뢰 체인 을 만 드 는 과정 에 대해 상세 하 게 공 유 했 습 니 다.두 번 째 부분 은 의뢰 의 한계점 을 지적 한 다음 에 GetInvocationList 방법 을 호출 하여 의뢰 배열 로 돌아 갑 니 다.그러면 의뢰 배열 의 모든 의뢰 를 옮 겨 다 니 며 의뢰 의 호출 과정 을 알 릴 수 있 습 니 다.이렇게 하면 위탁 체인 의 호출 에 대해 더 많은 통 제 를 할 수 있다.이 세 가지 주 제 를 통 해 의뢰 에 대한 소 개 를 통 해 여러분 들 이 의뢰 에 대해 더욱 깊이 이해 할 것 이 라 고 믿 습 니 다.그리고 왜 세 가지 주 제 를 써 서 의뢰 를 상세 하 게 소개 해 야 합 니까?주로 다음 에 소개 할 사건 입 니 다.Lambda 표현 식,Linq 의 내용 은 모두 의뢰 와 관련 이 있 기 때문에 의뢰 를 잘 이해 하 는 것 이 뒤의 특성의 기초 가 될 것 입 니 다.이런 것들 이 여러분 에 게 도움 이 되 기 를 바 랍 니 다.저 는 다음 주제 에서 사건 을 소개 하 겠 습 니 다.
이상 은 c\#의뢰 체인 에 대한 상세 한 내용 입 니 다.c\#의뢰 체인 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 하 세 요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C#Task를 사용하여 비동기식 작업을 수행하는 방법라인이 완성된 후에 이 라인을 다시 시작할 수 없습니다.반대로 조인(Join)만 결합할 수 있습니다 (프로세스가 현재 라인을 막습니다). 임무는 조합할 수 있는 것이다. 연장을 사용하여 그것들을 한데 연결시키는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.