>  기사  >  백엔드 개발  >  C#의 대리자 인스턴스 코드에 대한 자세한 설명(그림 및 텍스트)

C#의 대리자 인스턴스 코드에 대한 자세한 설명(그림 및 텍스트)

黄舟
黄舟원래의
2017-03-29 11:40:431625검색

이 글에서는 주로 C#에서의 위임 관련 지식을 소개합니다. 일정한 참고값이 있는데, 아래 에디터를 통해 살펴보겠습니다

위임은 이해하기가 쉽지 않은데 업무에서 자주 사용하는 말인데 정말 놀랍습니다. 애증의 감정인데, 이로 인해 많은 분들이 괴로움을 겪으셨을 거라 믿습니다.

위임이라고 하면 C 언어를 배웠다면 바로 함수 포인터가 떠오를 겁니다.

위임이란 무엇인가요? 대리자는 C#에서 유형안전하며 동일한 서명 방법을 사용하여 하나 이상의 함수 포인터를 구독할 수 있습니다. 위임은 함수를 매개변수로 전달할 수 있으며 실제 의미는 다른 사람이 귀하를 대신하여 행동하도록 하는 것입니다. 정수는 정수변수로 가리킬 수 있습니다. 객체는 개체 변수

함수 위임 변수를 사용하여 이를 가리킬 수도 있습니다. 대리자 유형은 하나의 메서드만 정의하는

인터페이스로 생각하고, 대리자 인스턴스는 해당 인터페이스를 구현하는 개체로 생각할 수 있습니다.

대리자를 사용하려면 다음 4가지 조건을 충족해야 합니다.

  • 대리자 유형을 선언합니다.

  • 실행해야 하는 필수 코드가 포함된 메서드

  • 는 위임 인스턴스를 생성해야 합니다.

  • 은 위임 인스턴스를 호출해야 합니다.

위임 선언

위임 선언 방법 : 위임 반환 값 유형 위임 유형 이름(매개 변수)

위임 선언은 반환 유형 키워드 앞에 추가 대리자 키워드가 있다는 점을 제외하면 기본적으로 인터페이스 메서드 선언과 동일합니다. 또한 대리자는 언제든지 다른 사람이 호출할 수 있으므로 일반적으로 공개 형식으로 선언됩니다.

위임의 본질도 유형이다. 클래스가 인스턴스화될 수 있고 대리자도 인스턴스화될 수 있다고 선언합니다.

델리게이트에는 다음과 같은 4가지 종류가 있습니다.

//1.无参数无返回值
    public delegate void NoParaNoReturnEventHandler();
    //2.有参数无返回值
    public delegate void WithParaNoReturnEventHandler(string name);
    //3.无参数有返回值
    public delegate string NoParaWithReturnEventHandler();
    //4.有参数有返回值
    public delegate string WithParaWithReturnEventHandler(string name);

코드에서 작업을 수행하고 싶지만 작업의 세부 사항을 모르는 경우 일반적으로 델리게이트를 사용하면 됩니다. 예를 들어, Thread 클래스가 새 스레드에서 무엇을 실행할지 아는 유일한 이유는 새 스레드를 시작할 때 ThreadStart 또는 ParameterizedThreadStart 대리자 인스턴스가 제공되기 때문입니다.

Thread th = new Thread(Test);
th.Start();
public Thread(ThreadStart start);
public delegate void ThreadStart();

ThreadStart는 매개변수와 반환 값이 없는 대리자입니다.

    static void Test()
    {
      Console.WriteLine("线程方法");
    }

이 Test 메서드의 함수 서명은 대리자 ThreadStart의 함수 서명과 일치해야 합니다.

대리자 호출

대리자를 먼저 인스턴스화한 다음 호출해야 합니다.

함수 서명과 위임자 서명이 일치해야 합니다.

NoParaNoReturnEventHandler _NoParaNoReturnEventHandler = ConsoleInfo;, 컴파일러는 새로운 작업을 수행하는 데 도움이 되지만 함수 호출이 되므로 NoParaNoReturnEventHandler _NoParaNoReturnEventHandler = ConsoleInfo();

로 작성할 수는 없습니다. .

#region 无返回值委托调用
    public static void Show()
    {
      //实例化委托
      NoParaNoReturnEventHandler _NoParaNoReturnEventHandler = new NoParaNoReturnEventHandler(ConsoleInfo);
      //NoParaNoReturnEventHandler _NoParaNoReturnEventHandler = ConsoleInfo; //简写
      //委托调用 通过Invoke()调用,或者可以直接省略
      _NoParaNoReturnEventHandler.Invoke();
      //_NoParaNoReturnEventHandler();
    }
    private static void ConsoleInfo()
    {
      Console.WriteLine("无参数无返回值的函数调用");
    } 
    #endregion

위임이 없으면 비동기도 없고 비동기도 바로 위임이 있기 때문입니다.

_NoParaNoReturnEventHandler.BeginInvoke(null,null); //비동기 호출

대리자를 사용하는 이유

메서드를 직접 호출할 수 있는 이유는 무엇입니까? 대리인을 통해 호출해야 합니까? 위임이란 무엇을 의미합니까?

분리되어 수정이 불가능하고 확장이 가능합니다. 논리적 분리.

대리자를 함수의 상위 클래스 또는 메서드의 자리 표시자로 생각할 수 있습니다.

코드를 살펴보겠습니다. 영어로 말하는 메소드와 중국어로 말하는 메소드가 있는데, 이 두 메소드의 함수 시그니처는 동일합니다.

public static void SayChinese(string name)
    {
      Console.WriteLine("你好," + name);
    }
    public static void SayEnglish(string name)
    {
      Console.WriteLine("hello," + name);
    }

그래서 외부에서 호출할 때

  MyDelegate.SayChinese("张三");
  MyDelegate.SayEnglish("zhangsan");

이 두 가지 메서드를 서로 다르게 호출하려면 서로 다른 호출 코드를 작성해야 하나요

그냥 어떻게 될까요? 메소드 호출? 코드를 다음과 같이 수정합니다.

public static void Say(string name,WithParaNoReturnEventHandler handler)
    {
      handler(name);
    }
   public static void SayChinese(string name)
    {
      Console.WriteLine("你好," + name);
    }
    public static void SayEnglish(string name)
    {
      Console.WriteLine("hello," + name);
    }

이런 방식으로 Say라는 메서드 하나만 호출됩니다.

어떻게 부르나요? 다음 세 가지 호출 방법은 다음과 같습니다.

      WithParaNoReturnEventHandler _WithParaNoReturnEventHandler = new WithParaNoReturnEventHandler(MyDelegate.SayChinese);
      MyDelegate.Say("张三",_WithParaNoReturnEventHandler);
      MyDelegate.Say("张三", delegate(string name) { Console.WriteLine("你好," + name); }); //匿名方法
      MyDelegate.Say("张三", (name) => { Console.WriteLine("你好," + name); }); //lambda表达式

위 코드에서는 C# 업그레이드를 통해 지속적으로 최적화되는 여러 호출 방법을 사용합니다. 첫 번째는 C# 1.0에 존재했던 전통적인 호출 메서드이고, 두 번째는 C# 2.0의 메서드를 호출하는 익명 메서드입니다. 소위 익명 메서드는 메서드를 사용할 때 익명 메서드를 사용하는 것이 가장 적합합니다. 하지만 딱 한 번만 호출됩니다. C#3의 람다 표현식. 실제로 일반 대리자도 지원되며, .NET 3.5에서는 한 단계 더 나아가 지정된 형식의 여러 매개 변수를 가져오고 지정된 형식의 다른 값을 반환할 수 있는 Func라는 일반 대리자 형식 집합을 도입합니다.

람다 표현식

람다 표현식의 본질은 메소드, 익명 메소드입니다.

메서드 본문에 한 줄만 있고 반환 값이 없는 경우 중괄호와 세미콜론도 제거할 수 있습니다.

MyDelegate.Say("张三", (name) => Console.WriteLine("你好," + name));

如果方法体只有一行,有返回值,可以去掉大括号和return。

WithParaWithReturnEventHandler _WithParaWithReturnEventHandler = (name)=>name+",你好";

从.NET3.5开始,基本上不需要我们自己来申明委托了,因为系统有许多内置的委托。

Action和Func委托,分别有16个和17个重载。int表示输入参数,out代表返回值,out参数放置在最后。

Action表示无返回值的委托,Func表示有返回值的委托。因为方法从大的角度来分类,也分为有返回值的方法和无返回值的方法。

也就是说具体调用什么样的方法,完全由调用方决定了,就有了更大的灵活性和扩展性。为什么这么说,如果我有些时候要先说英语再说汉语,有些事时候要先说汉语再说英语,如果没有委托,我们会怎么样实现?请看如下代码:

public static void SayEnglishAndChinese(string name)
    {
      SayEnglish(name);
      SayChinese(name);
    }
    public static void SayChineseAndEnglish(string name)
    {
      SayChinese(name);
      SayEnglish(name);
    }

如果又突然要添加一种俄语呢?被调用方的代码又要修改,如此循环下去,是不是要抓狂了?随着不断添加新语种,代码会变得越来越复杂,越来越难以维护。这样的代码耦合性非常高,是不合理的,也就是出现了所谓的代码的坏味道,你可以通过设计模式(如观察者模式等),在不使用委托的情况下来重构代码,但是实现起来是非常麻烦的,要写很多更多的代码...

委托可以传递方法,而这些方法可以代表一系列的操作,这些操作都由调用方来决定,就很好扩展了,而且十分灵活。我们不会对已有的方法进行修改,而是只以添加方法的形式去进行扩展。

可能有人又会说,我直接在调用方那里来一个一个调用我要执行哪些方法一样可以实现这样的效果啊?

可你有没有想过,你要调用的是一系列方法,你根本无法复用这一系列的方法。使用委托就不一样了,它好比一个方法集合的容器,你可以往里面增减方法,可以复用的。而且使用委托,你可以延时方法列表的调用,还可以随时对方法列表进行增减。委托对方法进行了再一次的封装。

总结:也就是当你只能确定方法的函数签名,无法确定方法的具体执行时,为了能够更好的扩展,以类似于注入方法的形式来实现新增的功能,就能体现出委托的价值。

委托和直接调用函数的区别:用委托就可以指向任意的函数,哪怕是之前没定义的都可以,而不用受限于哪几种。

多播委托

组合的委托必须是同一个类型,其相当于创建了一个按照组合的顺序依次调用的新委托对象。委托的组合一般是给事件用的,用普通委托的时候很少用。

通过+来实现将方法添加到委托实例中,-来从委托实例中进行方法的移除。

+和-纯粹是为了简化代码而生的,实际上其调用的分别是Delegate.Combine方法和Delegate.Remove。

如果委托中存在多个带返回值的方法,那么调用委托的返回值是最后一个方法的返回值。

public static void MultipleShow()
    {
      //多播委托
      NoParaWithReturnEventHandler _NoParaWithReturnEventHandler = new NoParaWithReturnEventHandler(GetDateTime);
      _NoParaWithReturnEventHandler += GetDateTime;
      Console.WriteLine(_NoParaWithReturnEventHandler());
    }
    public static string GetDateTime()
    {
      return string.Format("今天是{0}号。", DateTime.Now.Day.ToString());
    }

委托总结:

  • 委托封装了包含特殊返回类型和一组参数的行为,类似包含单一方法的接口;

  • 委托类型声明中所描述的类型签名决定了哪个方法可用于创建委托实例,同时决定了调用的签名;

  • 为了创建委托实例,需要一个方法以及(对于实例方法来说)调用方法的目标;

  • 委托实例是不易变的,就像String一样;

  • 每个委托实例都包含一个调用列表——一个操作列表;

  • 이벤트는 위임 인스턴스가 아닙니다. 단지 추가/제거 메서드 쌍이 있습니다(속성의 getter/할당 메서드와 유사).

일반적인 사용 시나리오: 양식 값 전송, 스레드 시작 시 바인딩 방법, 람다 식, 비동기 등

실제 사례: 지금은 모두가 기차표를 구하고 있지 않나요? 클라우드를 사용하여 표를 구하는 것은 위탁을 사용하는 것과 같습니다. 직접 표를 구매하거나 클라우드에서 표를 호스팅할 수 있습니다. 티켓을 직접 받으려면, 촬영할 때 항상 새로고침을 해야 하고, 주문할 때 인증코드를 입력해야 합니다. 클라우드 티켓을 이용하는 경우에는 입력만 하면 됩니다. 티켓을 발매하기 전에 티켓 예매 정보를 미리 알면 더 이상 필요하지 않습니다. 당신이 담당하고 티켓이 자동으로 발행되며 Cloud Ticket Grabbing이 티켓 예매에 어떻게 도움이 되는지 알 필요가 없습니다. 동일한 시간과 열차 번호를 위임 인스턴스로 만들 수 있으며, 많은 사람들이 이 위임 인스턴스를 사용하여 티켓을 구매합니다.

위 내용은 C#의 대리자 인스턴스 코드에 대한 자세한 설명(그림 및 텍스트)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.