it-swarm.com.ru

Вызов статического метода интерфейса C # с обобщениями

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

interface I
{
     static  string GetClassName();
}

public class Helper
{

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

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

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.

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

24
Keith

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

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

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

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

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

7
Dykam

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

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

3
Nick Clarke

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

public class Helper
{
    static void PrintClassName<T>()
    {
         Console.WriteLine(typeof(T).Name);
    }
}
3
Kent Boogaart

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

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

2
Mike J

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

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 непосредственно в самом методе как на переменную, вам придется передать экземпляр в приложение.

1
Wolfwyrd

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

0
codymanix