2017-07-19 75 views
-1

爲什麼MyDeler是「靜態」的,就像我可以通過類名訪問MyDeler一樣,但我無法明確地說public「static」delegate void MyDeler(),我也無法訪問d通過MyClass的實例,就像在新的MyClass.d()中一樣?Action與代理實例化和可訪問性之間的區別

此外,爲什麼我需要新建一個MyClass才能使用MyVoidAction?

見下面的代碼:

using System; 

public class MyClass 
{ 
    public delegate void MyDeler(); 
    public Action MyVoidAction; 
} 

class MainClass 
{ 
    static void Main() 
    { 
     MyClass.MyDeler d =() => Console.WriteLine("my deler"); 
     d(); 
     // MyClass.MyVoidAction mva1 =() => Console.WriteLine("my void action"); // not allowed, why? 
     MyClass meClass = new MyClass(); 
     meClass.MyVoidAction =() => Console.WriteLine("my void action"); 
     meClass.MyVoidAction(); 
    } 
} 

我擡頭一看這個答案:Accessibility between Action and Delegate

這清除了很多,但我不知道我是100%這一點。因此,根據該答覆,委託無效MyDeler()定義了一個類型,它混淆了我,因爲我想是這樣的:

using System; 

class MainClass 
{ 
    class MyClass 
    { 
     public static class DelegateClass 
     { 
      public void DoDel() // isn't even legal? 
      { 
       Console.WriteLine("DoDel()"); 
      } 
     } 
    } 
    static void Main() 
    { 
     //MyClass.DelegateClass d = new asdf // ??? something like this? 
    } 
} 

幫助讚賞!

回答

0

讓我們來揭穿這一點:

當你聲明MyDeler

public delegate void MyDeler(); 

你在做什麼是定義一個類型的方法,其執行將被「下放」到。換句話說,你說在這個簽名後面有方法,我打算繼續引用它。爲了使編譯器識別這些引用,將使用此類型。

因此,您將需要真正的指向該方法的實際指針,因爲這只是您的「定義」。這就是爲什麼你需要鍵入「MyDeler」的變量可以給它分配的實際方法調用:

MyClass.MyDeler d =() => Console.WriteLine("my deler"); 

這條線說:「創建一個名爲MyClass.MyDelerd變量保存一個參考這個內嵌方法」。從這裏開始,當您撥打d();時,指針將實際執行內聯方法。

對於動作:

public Action MyVoidAction; 

您現在宣佈類的公共財產。因此,在使用此屬性之前,您需要該類的一個實例。

這裏的技巧是Action是一個委託的已知定義。微軟有一個內置的類型,你可以使用而不是聲明你自己的void MyDeler();。它本質上是語法糖,但要記住,它仍然是一個類型,因爲你已經創建了一個公共財產,你現在需要給它分配將實際執行的方法和我們之前討論的那樣,你需要一個實例:

MyClass meClass = new MyClass(); //Instance creation 
meClass.MyVoidAction =() => Console.WriteLine("my void action"); //Tell your delegate what to delegate to. 
meClass.MyVoidAction(); //Run the inline method! 

我希望有所幫助。

0

MyDeler類型聲明,而不是變量聲明。你不能存儲它或分配給它。

要創建一個字段,用於存儲MyDeler例如,這行添加到MyClass

public MyDeler MyDelerField; 

現在你可以分配給它。

0

爲什麼MyDeler「靜態」,在我可以通過類名訪問MyDeler,但我不能明確地說公衆「靜態」委託無效MyDeler(),我也可以訪問d至實例MyClass,如新的MyClass.d()?

MyDeler聲明聲明一個型內MyClass。它類似於聲明任何其他嵌套類型,如:

class MyClass 
{ 
    public class MyNestedClass { } 
} 

這是MyClass的一員,不是的MyClass任何實際的實例,甚至也不是類MyClass作爲static成員會。

嵌套類型既不是「實例」也不是「靜態」,因爲它是類型系統的一部分,而不是類本身的一部分。

爲什麼需要新建一個MyClass才能使用MyVoidAction?

由於MyVoidAction的類的成員,並且是實例構件。所以你需要有一個實例來訪問它。

的委託無效MyDeler()定義了一個類型,它混淆了我,因爲我想象這樣的事情

你在public static class DelegateClass是做一些完全不同的那個例子聲明。 C#的一個不幸的方面是使用static來引用各種不同的東西。它不像Java那樣糟糕,但它仍然可能令人困惑(正如你發現的那樣)。

在該聲明中,這個詞的使用static的不使DelegateClass包含類型MyClass的「靜態成員」。作爲class聲明的一部分,static這個詞意味着整個類別將僅包含static成員。

因此,當您聲明DoDel()沒有static關鍵字時,您試圖在您承諾只聲明靜態成員的類中聲明實例成員,即該方法。如果將static添加到方法聲明中,它會編譯。

不這樣做會使DelegateClass類在該示例中類似於MyVoidAction成員。它仍然是一個類型的聲明,在MyClass類中聲明嵌套類型,並且仍然遵循類型規則,而不是類成員。但是我希望至少向你解釋爲什麼這個讓你感到困惑的例子就是它的運作方式。

+0

啊,真的逗我的大腦。我以前不熟悉嵌套類。 – reincarnationofstackexchange

0

Actiondelegate沒有參數的方法,並且返回void在形式上是相同的東西。

如果妳去看一下:https://msdn.microsoft.com/en-us/library/system.action(v=vs.110).aspx你可以看到:

您可以使用該委託傳遞的方法作爲參數,而不 明確聲明自定義委託。

我希望這個例子可以幫助:

public delegate void DelegateMyDeler(); //This is a custom delegate 

public class MyClass 
{ 
    public DelegateMyDeler MyDeler; //This use your custom delegate 
    public Action MyVoidAction; // This use Action delegate 
} 

class MainClass 
{ 
    static void Main() 
    { 
     // MyClass.MyDeler d =() => Console.WriteLine("my deler"); // Now this is not allowed too! 
     // d(); 
     // MyClass.MyVoidAction mva1 =() => Console.WriteLine("my void action"); // not allowed, why? 
     MyClass meClass = new MyClass(); 

     meClass.MyDeler =() => Console.WriteLine("my deler"); 
     meClass.MyDeler(); 

     meClass.MyVoidAction =() => Console.WriteLine("my void action"); 
     meClass.MyVoidAction(); 

     //but you can do (you custom delegate is defined out of the class in this case 
     //so you have not to add the class prefix): 
     DelegateMyDeler d =() => Console.WriteLine("my deler 2"); 
     d(); 

     // or 
     DelegateMyDeler d3 =() => Console.WriteLine("my deler 3"); 
     d3.Invoke(); 

     // and in a real case, for example: 
     DelegateMyDeler undeterminedMethod; 

     int x = 3; 
     switch (x) 
     { 
      case 1: 
       undeterminedMethod = deler1; 
       break; 
      case 2: 
       undeterminedMethod = deler2; 
       break; 
      case 3: 
       undeterminedMethod = deler3; 
       break; 
      default: 
       undeterminedMethod = null; 
       break; 
     } 

     undeterminedMethod?.Invoke(); //In case x is minor than 1 or major than 3, nothing happens 

    } 

    static void deler1() { Console.WriteLine("my deler 1"); } 
    static void deler2() { Console.WriteLine("my deler 2"); } 
    static void deler3() { Console.WriteLine("my deler 3"); } 
} 
相關問題