Вызов статического метода интерфейса С# с дженериками
Есть ли простой способ реализовать это и, если возможно, не инициировать объект:
interface I
{
static string GetClassName();
}
public class Helper
{
static void PrintClassName<T>() where T : I
{
Console.WriteLine(T.GetClassName());
}
}
Ответы
Ответ 1
Попробуйте вместо этого использовать метод расширения:
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.
У вас не может быть интерфейсов для статических методов, потому что это не имеет смысла, они являются методами утилиты без экземпляра и, следовательно, у них действительно нет типа.
Ответ 2
Вы не можете наследовать статические методы. Из-за этого ваш код не будет компилироваться, потому что из-за этого у интерфейса не может быть статических методов.
Как указано из littleguru:
Наследование в .NET работает только на база экземпляров. Статические методы определяется на уровне типа не на уровень экземпляра. Вот почему переопределение не работает со статическими методы/свойства/события...
Статические методы удерживаются только один раз в Память. Нет виртуальной таблицы и т.д. созданный для них.
Если вы вызываете метод экземпляра в .NET, вы всегда даете пример. Это скрыто .NET. но это происходит. Каждый экземпляр метод имеет в качестве первого аргумента указатель (ссылку) на объект, метод запускается. Это не происходит со статическими методами (поскольку они определенные на уровне типа). Как следует компилятор решил выбрать метод для вызова?
Ответ 3
Я также пытался установить статический метод на интерфейсе некоторое время назад, не уверен, почему сейчас. Я сделал закладку, поэтому, возможно, это помогает:
Интерфейс со статическим методом с использованием методов расширения
Ответ 4
Если вы только после имени типа, вы можете просто сделать это:
public class Helper
{
static void PrintClassName<T>()
{
Console.WriteLine(typeof(T).Name);
}
}
Ответ 5
Объявление static
property
, event
или method
в определении интерфейса не считается юридическим определением. Это связано с тем, что интерфейсы считаются контрактами и как таковые представляют собой то, что будет реализовано каждым клиентским экземпляром этого интерфейса.
В объявлении A static
говорится, что член static
не требует реализации физического клиента для выполнения требуемых функций, и это не соответствует общей концепции интерфейсов: предоставление проверенного контракта.
Ответ 6
Ответ - это квалифицированный "не совсем, а Сортировка". Вы можете предоставить статический метод расширения всем разработчикам данного интерфейса и затем вызывать это от своего исполнителя в свойстве или другом методе. В качестве примера:
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), который применяется ко всем членам его типа, который выполняет работу по поиску нужной нам информации. У нас есть класс (пример), который реализует интерфейс I, поэтому, когда мы вызываем наш статический вспомогательный класс, проходящий в экземпляре примера, он запускает против него статический метод. К сожалению, неверно ссылаться на тип T непосредственно внутри самого метода как переменной, вам нужно будет передать экземпляр в приложение.
Ответ 7
Вы можете определить className как атрибут для определенного класса. Это предпочтительнее хранить метаданные в .net. Таким образом, вы можете запросить атрибут для данного класса, и вам не нужен экземпляр.