Вызов статического метода интерфейса C # с обобщениями - PullRequest
28 голосов
/ 07 августа 2009

Есть ли простой способ реализовать это и, если возможно, без создания экземпляра объекта:

interface I
{
     static  string GetClassName();
}

public class Helper
{

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

Ответы [ 7 ]

25 голосов
/ 07 августа 2009

Попробуйте вместо этого метод расширения:

public interface IMyInterface
{
     string GetClassName();
}

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

Это позволяет вам добавить метод статического расширения / утилиты, но вам все еще нужен экземпляр вашей реализации IMyInterface.

У вас не может быть интерфейсов для статических методов, потому что это не имеет смысла, они являются служебными методами без экземпляра и, следовательно, у них действительно нет типа.

7 голосов
/ 07 августа 2009

Нельзя наследовать статические методы. Ваш код никак не компилируется, потому что интерфейс не может иметь статические методы из-за этого.

Как указано в littleguru :

Наследование в .NET работает только на база экземпляров. Статические методы определяется на уровне типа, а не на уровень экземпляра. Вот почему переопределение не работает со статическим методы / свойства / события ...

Статические методы проводятся только один раз в объем памяти. Нет виртуального стола и т. Д. это создано для них.

Если вы вызываете метод экземпляра в .NET, вы всегда даете ему текущий пример. Это скрыто .NET время выполнения, но это случается. Каждый экземпляр метод имеет в качестве первого аргумента указатель (ссылка) на объект, который метод запущен. Этого не происходит со статическими методами (как они есть определяется на уровне типа). Как следует компилятор решает выбрать метод для вызова?

3 голосов
/ 07 августа 2009

Если вы только после имени типа, вы можете просто сделать это:

public class Helper
{
    static void PrintClassName<T>()
    {
         Console.WriteLine(typeof(T).Name);
    }
}
3 голосов
/ 07 августа 2009

Я также пытался настроить статический метод на интерфейсе некоторое время назад, не знаю, почему сейчас. Я сделал закладку на это, так что, возможно, это поможет:

Интерфейс со статическим методом с использованием методов расширения

2 голосов
/ 07 августа 2009

Объявление static property, event или method в определении интерфейса не считается юридическим определением. Это связано с тем, что интерфейсы считаются контрактами и, как таковые, представляют собой нечто, что будет реализовываться каждым клиентским экземпляром этого интерфейса.

В декларации static по существу говорится, что элемент static не требует физической реализации клиента для выполнения требуемой функциональности, и это не соответствует общей концепции интерфейсов: предоставление проверенного договора.

1 голос
/ 07 августа 2009

Ответ квалифицированный "не совсем, но вроде". Вы можете предоставить метод статического расширения всем разработчикам данного интерфейса, а затем вызвать его из своего разработчика в свойстве или другом методе. Как пример:

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

Здесь у нас есть интерфейс (I), который определяет свойство, о котором мы заботимся, и метод статического расширения (GetClassName), который применяется ко всем членам его типа, который выполняет основную работу по получению необходимой нам информации. У нас есть класс (Example), который реализует интерфейс I, поэтому, когда мы вызываем наш статический вспомогательный класс, передавая экземпляр класса Example, он запускает статический метод для него. К сожалению, недопустимо ссылаться на тип T непосредственно внутри самого метода как на переменную, вам придется передать экземпляр в приложение.

0 голосов
/ 27 сентября 2009

Вы можете определить className как атрибут определенного класса. Это предпочтительный способ хранения метаданных в .net. Таким образом, вы можете запросить атрибут для данного класса, и вам не нужен экземпляр.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...