interface I
{
static string GetClassName();
}
public class Helper
{
static void PrintClassName<T>() where T : I
{
Console.WriteLine(T.GetClassName());
}
}
interface I
{
static string GetClassName();
}
public class Helper
{
static void PrintClassName<T>() where T : I
{
Console.WriteLine(T.GetClassName());
}
}
可以尝试使用扩展方法:
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实现的实例。
您不能为静态方法创建接口,因为这没有意义,它们是没有实例的实用方法,因此它们实际上没有类型。
IParsable<T>
,它定义了一个静态的Parse
和TryParse
方法。 - Mitch Dennypublic class Helper
{
static void PrintClassName<T>()
{
Console.WriteLine(typeof(T).Name);
}
}
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作为变量是无效的,您必须将实例传递到应用程序中。
你可以将className定义为特定类的属性。这是在.NET中存储元数据的首选方式。这样,您可以查询给定类的属性,而不需要实例。
是的,你可以 - 在某种程度上 - 如果你不介意定义新类型来代理实例调用静态方法:
虽然一个 interface
只能声明实例成员,但你可以使用 C# 的泛型的一些简单技巧,而不需要反射,来完成你想要的功能(而且不会采用 Java 风格的 AbstractFactoryBeanFactory
设计模式过度使用)。
我们可以做的是,定义一个单独的 struct
(即值类型),其中包含调用我们想要的静态成员的实例成员。
所以如果我们有这个接口:
interface IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance();
}
...我们想要做类似这样的事情:
void AGenericMethodThatDoesntHaveAnInstanceOfT<T>()
{
T.DoSomethingWithoutAnObjectInstance();
}
如果这样,我们可以这样做:
void AGenericMethodThatDoesntHaveAnInstanceOfT<T>()
where T : struct, IStaticFunctionality
{
T t = default;
t.DoSomethingWithoutAnObjectInstance();
// Note the above code uses `T t default;` instead of `T t = new T()`.
// This is because the C# compiler currently replaces `new T()` with `Activator.CreateInstance<T>()` in the generated bytecode.
// This has poor performance compared to `default(T)` or a normal non-generic constructor call, but the compiler does this because it's a workaround for a design-bug back in C# 6.0: https://devblogs.microsoft.com/premier-developer/dissecting-the-new-constraint-in-c-a-perfect-example-of-a-leaky-abstraction/
}
所以,如果我们有不同类型的 static void DoSomethingWithoutAnObjectInstance
方法,我们只需要为每种类型定义 IStaticFunctionality
的 struct
实现:
class Foo
{
public static void DoSomethingWithoutAnObjectInstance()
{
Console.WriteLine("foo");
}
struct Static : IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance() => Foo.DoSomethingWithoutAnObjectInstance();
}
}
class Bar
{
public static void DoSomethingWithoutAnObjectInstance()
{
Console.WriteLine("bar");
}
struct Static : IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance() => Bar.DoSomethingWithoutAnObjectInstance();
}
}
那么一个调用 AGenericMethodThatDoesntHaveAnInstanceOfT<Foo>
的调用点实际上看起来像:
AGenericMethodThatDoesntHaveAnInstanceOfT<Foo.Static>();
typeof(T).FullName
能完成任务吗? - Eric Smith