2009-08-07 13 views
26

Czy istnieje prosty sposób do wdrożenia tego, a jeśli jest to możliwe bez instanciating obiektu:C statyczna metoda połączenia z rodzajowych

interface I 
{ 
    static string GetClassName(); 
} 

public class Helper 
{ 

    static void PrintClassName<T>() where T : I 
    { 
     Console.WriteLine(T.GetClassName()); 
    } 
} 
+0

Jak wyglądałaby implementacja interfejsu? – dtb

+2

Biorąc pod uwagę, że interfejsy definiują elementy instancji, w jaki sposób można wywołać członka interfejsu bez instancji? jeśli chcesz nazwę klasy, użyj typeof (T) i zrzuć interfejs. – meandmycode

+0

Co próbujesz tutaj osiągnąć? Pewnie, że 'typeof (T) .FullName' wykonałby zadanie? –

Odpowiedz

24

Wypróbuj metodę rozszerzenia zamiast:

public interface IMyInterface 
{ 
    string GetClassName(); 
} 

public static class IMyInterfaceExtensions 
{ 
    public static void PrintClassName<T>(this T input) 
     where T : IMyInterface 
    { 
     Console.WriteLine(input.GetClassName()); 
    } 
} 

To pozwala na dodanie statycznej metody rozszerzenie/użytkową, ale trzeba jeszcze instancji implementacji IMyInterface.

Nie można mieć interfejsów do metod statycznych, ponieważ nie ma to sensu, są to metody użytkowe bez instancji, a więc tak naprawdę nie mają typu.

+0

Ok, ale czy myślisz, że możemy uniknąć parametru wejściowego. Powiedzmy, że mamy jakiś singletowy wzór interfejsu lub w jakikolwiek inny sposób? – Toto

+1

Pamiętaj, co masz na myśli - możesz nazwać te metody rozszerzenia tak, jakby były instancją jeden: new MyImplementation(). PrintClassName() – Keith

+2

Nie można uniknąć wystąpienia, chyba że przełączysz się na używanie refleksji (np. @Kent Boogaart's odpowiedź), ale wtedy nie powinieneś używać generycznych, ponieważ właśnie przekazujesz typ – Keith

7

Nie można dziedziczyć metody statyczne. Twój kod nie skompilowałby się w żaden sposób, ponieważ interfejs nie może mieć statycznych metod z tego powodu.

jako cytat z littleguru:

Dziedziczenie w .NET działa tylko na instancji bazy. Metody statyczne to zdefiniowane na poziomie typu, nie na poziomie instancji . Dlatego przesłanianie nie działa ze statycznymi metodami/właściwościami/zdarzeniami ...

Metody statyczne są przechowywane tylko raz w pamięci . Nie ma wirtualnego stołu itp. , który jest dla nich stworzony.

Jeśli wywołujesz metodę instancji w .NET, zawsze nadajesz jej bieżącą instancję . Jest to ukryte w środowisku wykonawczym .NET , ale tak się dzieje. Każda instancja ma jako pierwszy argument wskaźnik (odwołanie) do obiektu, na którym jest uruchamiana metoda . To się nie zdarza metodami statycznymi (ponieważ są one zdefiniowane na poziomie typu ). Jak powinien być kompilator decyduje się wybrać metodę do wywołania?

+1

Na pewno kompilator nie może wybrać (lub jeśli to możliwe, ponieważ wyraźnie nazywamy właściwy statyczny focntion właściwą klasą). Czy jednak nie możemy mieć czegoś takiego z genereiką? – Toto

+0

Prawdopodobnie to możliwe. Ale ten projekt został wybrany, aby zachować prostotę i czystość. – Dykam

3

Jeśli dopiero po nazwie typu, można po prostu to zrobić:

public class Helper 
{ 
    static void PrintClassName<T>() 
    { 
     Console.WriteLine(typeof(T).Name); 
    } 
} 
+0

Dobra odpowiedź (+1), ale dodam, że nie powinieneś tego robić - jeśli wszystko, co robisz, przekazuje typ, powinieneś użyć zwykłego parametru: PrintClassName (Type input) {Console.WriteLine (input .Nazwa); } – Keith

1

Odpowiedź jest kwalifikowany „nie bardzo, ale coś w rodzaju”. Możesz podać metodę statycznego rozszerzenia dla wszystkich implementatorów danego interfejsu, a następnie możesz wywołać to za pomocą swojego programisty w usłudze lub innej metodzie. Jako przykład:

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

namespace InterfacesWithGenerics 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Helper.PrintClassName<Example>(new Example()); 
      Console.ReadLine(); 
     } 
    } 

    public class Example : I 
    { 
     #region I Members 

     public string ClassName 
     { 
      get { return this.GetClassName(); } 
     } 

     #endregion 
    } 

    public interface I 
    { 
     string ClassName { get; } 
    } 

    public class Helper 
    { 

     public static void PrintClassName<T>(T input) where T : I 
     {   
      Console.WriteLine(input.GetClassName()) ; 
     } 
    } 

    public static class IExtensions 
    { 
     public static string GetClassName(this I yourInterface) 
     { 
      return yourInterface.GetType().ToString(); 
     } 
    } 
} 

Tutaj mamy interfejsu (I), który określa właściwość dbamy o oraz metodę rozszerzenia statyczne (GetClassName), który jest stosowany do wszystkich członków swojego typu, który działa grunt zachorowania informacje, które chcemy. Mamy klasę (przykład), która implementuje interfejs I, więc kiedy wywołujemy naszą statyczną klasę pomocniczą przechodzącą w instancji przykładu, uruchamia ona metodę statyczną.Niestety nie jest właściwe odwoływanie się do typu T bezpośrednio w samej metodzie jako zmiennej, musisz przekazać instancję do aplikacji.

2

Zgłoszenie staticproperty, event lub method w definicji interfejsu nie jest uważane za definicję prawną. Dzieje się tak dlatego, że interfejsy są traktowane jako umowy i jako takie reprezentują coś, co będzie implementowane przez każdą instancję klienta tego interfejsu.

Oświadczenie static zasadniczo stwierdza, że ​​członek static nie wymaga fizycznej implementacji klienta w celu wykonania wymaganej funkcjonalności, co nie jest zgodne z ogólną koncepcją interfejsów: zapewnienie sprawdzonej umowy.

0

Można zdefiniować ClassName jako atrybut dla określonej klasy. Jest to preferowane rozwiązanie do przechowywania metadanych w .net. W ten sposób możesz zapytać o atrybut dla danej klasy i nie potrzebujesz instancji.