有没有一种简单的方法来实现这一点,并且在可能的情况下不实例化对象:
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实现的实例。
您不能具有用于静态方法的接口,因为这没有意义,它们是没有实例的实用方法,因此它们实际上没有类型。
您不能继承静态方法。您的代码不会以任何方式进行编译,因为因此接口不能具有静态方法。
引自littleguru:
。NET中的继承仅适用于 实例库。静态方法是 在类型级别上定义而不在 实例级别。这就是为什么压倒一切 不适用于静态 方法/属性/事件...
静态方法只保留一次 记忆。没有虚拟表等。 为他们创造的。
如果您在 .NET,您总是给它最新的 实例。 .NET隐藏了它 运行时,但是它发生了。每个实例 方法具有第一个参数的指针 (参考) 方法正在运行。这不会发生 使用静态方法(因为它们是 在类型级别定义)。 应该如何 编译器决定选择 调用方法?
不久前,我也试图在接口上设置静态方法,现在不知道为什么。我将其添加为书签,因此可能有所帮助:
如果您只是键入类型名称,则可以执行以下操作:
public class Helper
{
static void PrintClassName<T>()
{
Console.WriteLine(typeof(T).Name);
}
}
在接口定义上声明static
property
,event
或method
不视为合法定义。这是因为接口被视为合同,因此代表该接口的每个客户端实例将实现的事物。
static
声明从本质上说,static
成员不需要物理客户端实现即可执行所需的功能,这不符合接口的一般概念:提供经过验证的合同。
答案是合格的“不是,但实际上是”。您可以为给定接口的所有实现者提供静态扩展方法,然后可以从实现者的属性或其他方法中调用此方法。例如:
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类型作为变量引用是无效的,您必须将实例传递给应用程序。
您可以将className定义为特定类的属性。这是将元数据存储在.net中的首选方法。这样,您可以查询给定类的属性,并且不需要实例。
是的,如果您不介意定义代理实例调用静态方法的新类型,则可以-排序-
虽然interface
只能声明instance成员,但是您可以对C#的泛型使用一些简单的技巧,而无需进行反思,即可完成您要执行的操作(并且无需使用Java样式的[C0 ]设计模式过度使用)。
[我们可以做的是定义一个单独的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
的struct
实现:
IStaticFunctionality
于是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>