2011-05-11 5 views
4

PrintOne을 두 번 등록 했으므로 다음 코드는 "PrintOne"메시지를 두 번 인쇄합니다. 여기에 질문이 있습니다C# - 중복 multicastdelegate 처리하는 방법?

질문 1> 왜 기본적으로 연산자 + = (즉, 결합)가 중복 된 메서드 처리기를 확인하지 못합니까?

질문 2> RegisterCall 메서드에서이 중복 호출을 피하는 방법? 나는 MulticastDelegate/Delegate에서 이미 호출 목록에있는 메서드가 있음을 알 수있는 메서드를 찾으려고합니다. 그러나 나는 그것을 발견하지 못했습니다. http://msdn.microsoft.com/en-us/library/system.multicastdelegate.aspx

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace app3 
{ 
    class Car 
    { 
     public delegate void PrintMethod(string msg); 

     public string Name { get; set; } 

     private PrintMethod printMethods; 

     public Car() { } 
     public Car(string name) { Name = name; } 

     public void PrintCar() 
     { 
      if (printMethods != null) 
      { 
       printMethods(this.ToString()); 
      } 
      else 
      { 
       Console.WriteLine("No Method will be called"); 
      } 
     } 
     public override string ToString() 
     { 
      return string.Format("Car Name is {0}: ", Name); 
     } 

     public static void PrintOne(string msg) 
     { 
      Console.WriteLine("PrintOne"); 
     } 

     public static void PrintTwo(string msg) 
     { 
      Console.WriteLine("PrintTwo"); 
     } 

     public void RegisterCall(PrintMethod methodToCall) 
     { 
      printMethods += methodToCall; 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Car mycar = new Car { Name = "BMW" }; 
      mycar.RegisterCall(new Car.PrintMethod(Car.PrintOne)); // **will print for the first time** 
      mycar.RegisterCall(new Car.PrintMethod(Car.PrintOne)); // **will print for the second time** 
      mycar.PrintCar(); 

      Console.ReadLine(); 
     } 
    } 
} 

답변

5
public void RegisterCall(PrintMethod methodToCall) 
{ 
    printMethods -= methodToCall; 
    printMethods += methodToCall; 
} 

이 멀티 캐스트 위임에 존재하는 경우 확인은 1 개 인스턴스를 보장하기 위해 추가 한 후, 제거 할 것입니다 감사합니다.

대부분의 시간 중복이 발생하지 않기 때문에 동일한 처리기에 대한 대리인이 멀티 캐스트 대리자에 이미있는 경우 처리기를 추가해도 중단되지 않습니다. 또한 동일한 메소드를 두 번 호출하는 것이 바람직한 (예 : 객체 또는 콜렉션의 사용자 정의 집계) 유효한 상황이 있습니다.

중복을 피하기로 결정한 경우 처리기를 추가 할 때 예외를 throw해야합니다. 비싸다는 것은 런타임에 발생했을 때와 추악한 try-catch 블록에서 발생하는 경우 모두 여러 가지면에서 비싸다.

1

C#에서 등록 된 콜백의 일반적인 디자인은 공개 event을 개체에 배치하는 것입니다. 이렇게하면 다른 클래스가 이벤트 핸들러를 추가하고 중요하게 제거 할 수 있습니다. C#의 기본 제공 이벤트 등록 기능을 사용하는 대신 RegisterCall 메서드를 사용하는 이유가 분명하지 않습니다.

일반적으로 이벤트에 이벤트 처리기를 추가하는 모듈은 호출이 더 이상 필요하지 않을 때 해당 처리기를 제거합니다. 이는 대리자가 객체 인스턴스에 대한 참조를 보유하고이를 유지하기 때문에 이벤트 생성 객체 자체보다 예상 수명이 짧은 이벤트 처리 객체에 필요합니다.

+1

곧 도착할 예정입니다. C#을 배우기 시작하십시오. – q0987

관련 문제