Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erläuterung des Delegierten-Instanzcodes in C# (Bild und Text)

Detaillierte Erläuterung des Delegierten-Instanzcodes in C# (Bild und Text)

黄舟
黄舟Original
2017-03-29 11:40:431625Durchsuche

In diesem Artikel werden hauptsächlich die relevanten Kenntnisse der Delegation in C# vorgestellt. Es hat einen gewissen Referenzwert, schauen wir es uns mit dem unten stehenden Editor an

Delegation ist nicht ganz einfach zu verstehen, wird aber häufig in der Arbeit verwendet, was wirklich überraschend ist. Es ist ein Gefühl der Hassliebe, und ich glaube, dass es vielen Menschen zu schaffen macht.

Wenn Sie die Sprache C gelernt haben, denken Sie beim Delegieren sofort an Funktionszeiger.

Was ist Delegation? Delegaten sind in C# typsicher und können mit derselben Signaturmethode auf einen oder mehrere Funktionszeiger abonniert werden. Die Delegation kann Funktionen als Parameter übergeben, und ihre eigentliche Bedeutung besteht darin, andere in Ihrem Namen handeln zu lassen. Ein Delegat kann als Zeiger auf eine Funktion betrachtet werden, auf die eine Ganzzahlvariable zeigen kann, auf eine Objektvariable Objekt und Funktion Sie können auch eine Delegate-Variable verwenden, um darauf zu verweisen. Wir können uns den Delegatentyp als eine Schnittstelle

vorstellen, die nur eine Methode definiert, und die Delegateninstanz kann man sich als ein Objekt vorstellen, das diese Schnittstelle implementiert.

Um einen Delegaten zu verwenden, müssen 4 Bedingungen erfüllt sein:

Den Delegatentyp deklarieren
  • Es muss eine geben Die Methode, die den auszuführenden Code enthält, muss eine Delegate-Instanz erstellen.
  • Deklaration der Delegation
  • Deklarationsmethode der Delegation: Rückgabewerttyp des Delegaten, Name des Delegattyps (Parameter)
  • delegiert Die Deklaration entspricht grundsätzlich der Deklaration der Schnittstellenmethode, mit der Ausnahme, dass vor dem Schlüsselwort für den Rückgabetyp ein zusätzliches Schlüsselwort „delegate“ steht. Außerdem wird ein Delegat im Allgemeinen als öffentlicher Typ deklariert, da er jederzeit von anderen aufgerufen werden kann.

    Das Wesen der Delegation ist auch ein Typ. Wir erklären, dass eine Klasse instanziiert werden kann und ein Delegat auch instanziiert werden kann.
Es gibt vier Arten von Delegaten:

Wenn der Code eine Operation ausführen möchte, aber die Details der Operation nicht kennt, können Sie im Allgemeinen Delegaten verwenden. Der einzige Grund, warum die Thread-Klasse beispielsweise weiß, was in einem neuen Thread ausgeführt werden soll, besteht darin, dass ihr beim Starten des neuen Threads eine ThreadStart- oder ParameterizedThreadStart-Delegateninstanz bereitgestellt wird.

ThreadStart ist ein Delegate ohne Parameter und ohne Rückgabewert.

Die Funktionssignatur dieser Testmethode muss mit der Funktionssignatur des Delegaten ThreadStart übereinstimmen.

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

Der Delegat muss zuerst instanziiert und dann aufgerufen werden.
Thread th = new Thread(Test);
th.Start();
public Thread(ThreadStart start);
public delegate void ThreadStart();

Die Signatur der Funktion und die des Delegierten müssen konsistent sein.

NoParaNoReturnEventHandler _NoParaNoReturnEventHandler = ConsoleInfo;,
    static void Test()
    {
      Console.WriteLine("线程方法");
    }
Der Compiler hilft uns bei der Ausführung neuer, kann aber nicht als

NoParaNoReturnEventHandler _NoParaNoReturnEventHandler = ConsoleInfo();

geschrieben werden, da es sich um einen Funktionsaufruf handelt .

Ohne Delegation gäbe es keine Asynchronität, und Asynchronität liegt genau an der Existenz der Delegation. _NoParaNoReturnEventHandler.BeginInvoke(null,null); //Asynchroner Aufruf

Warum einen Delegaten verwenden

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

Wir können die Methode direkt aufrufen, warum? Muss es über einen Delegierten aufgerufen werden? Was bedeutet Delegation?

Entkoppelt, verschlossen für Änderungen, offen für Erweiterungen. Logische Trennung.

Sie können sich einen Delegaten als die übergeordnete Klasse einer Funktion oder als Platzhalter für eine Methode vorstellen.

Werfen wir einen Blick auf den Code? Angenommen, es gibt zwei Methoden, eine spricht Englisch und eine spricht Chinesisch, und die Funktionssignaturen dieser beiden Methoden sind gleich.

Wenn wir dann extern anrufen,

Wenn wir diese beiden verschiedenen Methoden aufrufen möchten, müssen wir unterschiedliche Anrufcodes schreiben

Können wir? nur eine Methode aufrufen? Ändern Sie den Code wie folgt:

Auf diese Weise wird nur eine Methode, Say, aufgerufen.

public static void SayChinese(string name)
    {
      Console.WriteLine("你好," + name);
    }
    public static void SayEnglish(string name)
    {
      Console.WriteLine("hello," + name);
    }
Wie nennt man es? Die folgenden drei Aufrufmethoden:

  MyDelegate.SayChinese("张三");
  MyDelegate.SayEnglish("zhangsan");
Der obige Code verwendet mehrere Aufrufmethoden, und diese Aufrufmethoden werden mit der Aktualisierung von C# kontinuierlich optimiert. Die erste ist die traditionelle aufrufende Methode, die es in C# 1.0 gab, und die zweite ist die anonyme Methode, die in C# 2.0 aufgerufen wird. Die sogenannte anonyme Methode ist eine Methode ohne Namen. Es ist am besten, anonyme Methoden zu verwenden wird nur einmal aufgerufen. Aber das war's. Lambda-Ausdrücke in C#3. Tatsächlich werden auch generische Delegaten unterstützt, und .NET 3.5 geht noch einen Schritt weiter und führt eine Reihe generischer Delegatentypen namens Func ein, die mehrere Parameter eines bestimmten Typs abrufen und einen anderen Wert eines bestimmten Typs zurückgeben können.

Lambda-Ausdruck

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);
    }

Das Wesen des Lambda-Ausdrucks ist eine Methode, eine anonyme Methode.

Wenn der Methodenkörper nur eine Zeile und keinen Rückgabewert hat, können Sie auch die geschweiften Klammern und Semikolons entfernen.

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一样;

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

  • Ereignisse sind keine Delegate-Instanzen – nur gepaarte Add-/Remove-Methoden (ähnlich den Getter-/Zuweisungsmethoden der Eigenschaft).

Häufige Verwendungsszenarien: Formularwertübertragung, Bindungsmethode beim Threadstart, Lambda-Ausdruck, asynchron usw.

Beispiel aus dem wirklichen Leben: Schnappt sich jetzt nicht jeder Zugtickets? Die Nutzung der Cloud zum Ticketkauf ist gleichbedeutend mit der Nutzung von Vertrauen. Sie können die Tickets direkt selbst kaufen oder die Tickets in der Cloud hosten Um sich die Tickets selbst zu holen, müssen Sie sich jederzeit aktualisieren, wenn Sie eine Bestellung aufgeben usw. Wenn Sie Cloud-Ticket-Grabbing nutzen, müssen Sie nur eingeben Sie müssen die Ticket-Grabber-Informationen im Voraus abrufen, bevor Sie das Ticket freigeben. Sie haben die Verantwortung, die Tickets werden automatisch ausgestellt und Sie müssen nicht wissen, wie Cloud Ticket Grabbing Ihnen beim Ticket-Grabber hilft. Die gleiche Uhrzeit und Zugnummer können in eine Delegationsinstanz umgewandelt werden, und viele Leute nutzen diese Delegationsinstanz, um Fahrkarten zu ergattern.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des Delegierten-Instanzcodes in C# (Bild und Text). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn