为什么我不能声明C#方法是虚拟的还是静态的?

我有一个帮助器类,只是一堆静态方法,并希望inheritance辅助类。 有些行为是独特的,取决于子类,所以我想从基类调用一个虚拟方法,但由于所有的方法都是静态的,我不能创build一个普通的虚拟方法(为了访问虚拟方法需要对象引用)。

有没有办法解决? 我想我可以使用单身.. HelperClass.Instance.HelperMethod()并没有比HelperClass.HelperMethod()更糟糕。 布朗尼指出,任何人都可以指出一些支持虚拟静态方法的语言。

编辑:好吧,我疯了。 谷歌的search结果让我觉得我不在那里。

虚拟静态方法没有意义。 如果我打电话给HelperClass.HelperMethod(); 为什么我会期望一些随机子类的方法被调用? 当你有两个HelperClassHelperClass时,解决scheme真的会崩溃 – 你会使用哪一个?

如果你想拥有可重写的静态types的方法,你应该可以使用:

  • 一个单例,如果你想在全局使用相同的子类。
  • 如果您希望在应用程序的不同部分中使用不同的行为,则可以使用工厂或依赖项注入的传统类层次结构。

select哪种解决scheme在您的情况下更有意义。

我不认为你疯了。 你只是想使用当前在.NET中不可能的东西。

如果我们正在谈论generics,那么您对虚拟静态方法的请求将具有很大意义。 例如,我未来对CLRdevise师的要求是允许我写这样的inteface:

 public interface ISumable<T> { static T Add(T left, T right); } 

并像这样使用它:

 public T Aggregate<T>(T left, T right) where T : ISumable<T> { return T.Add(left, right); } 

但现在是不可能的,所以我这样做:

  public static class Static<T> where T : new() { public static T Value = new T(); } public interface ISumable<T> { T Add(T left, T right); } public T Aggregate<T>(T left, T right) where T : ISumable<T>, new() { return Static<T>.Value.Add(left, right); } 

事实上,这可以在Delphi中完成。 一个例子:

 type TForm1 = class(TForm) procedure FormShow(Sender: TObject); end; TTestClass = class public class procedure TestMethod(); virtual; end; TTestDerivedClass = class(TTestClass) public class procedure TestMethod(); override; end; TTestMetaClass = class of TTestClass; var Form1: TForm1; implementation {$R *.dfm} class procedure TTestClass.TestMethod(); begin Application.MessageBox('base', 'Message'); end; class procedure TTestDerivedClass.TestMethod(); begin Application.MessageBox('descendant', 'Message'); end; procedure TForm1.FormShow(Sender: TObject); var sample: TTestMetaClass; begin sample := TTestClass; sample.TestMethod; sample := TTestDerivedClass; sample.TestMethod; end; 

很有趣。 我不再使用Delphi,但我记得能够使用元类function非常容易地在自定义devise器canvas上创build不同types的控件:控件类,例如。 TButton,TTextBox等是一个参数,我可以使用实际的元类参数调用适当的构造函数。

那种可怜的人的工厂模式:)

只要有一个常规的静态方法,就可以达到相同的效果,然后用new关键字来隐藏它

 public class Base { //Other stuff public static void DoSomething() { Console.WriteLine("Base"); } } public class SomeClass : Base { public new static void DoSomething() { Console.WriteLine("SomeClass"); } } public class SomeOtherClass : Base { } 

然后你可以像这样调用方法

 Base.DoSomething(); //Base SomeClass.DoSomething(); //SomeClass SomeOtherClass.DoSomething(); //Base 

我来自Delphi,这是我在c#中非常想念的许多function之一。 Delphi将允许你创buildtypes化的types引用,并且你可以在需要父类的types的地方传递派生类的types。 这种对象types的处理具有强大的实用性。 特别是允许元数据的运行时间确定。 我可怕的混合语法在这里,但在C#它看起来像这样:

  class Root { public static virtual string TestMethod() {return "Root"; } } TRootClass = class of TRoot; // Here is the typed type declaration class Derived : Root { public static overide string TestMethod(){ return "derived"; } } class Test { public static string Run(){ TRootClass rc; rc = Root; Test(rc); rc = Derived(); Test(rc); } public static Test(TRootClass AClass){ string str = AClass.TestMethod(); Console.WriteLine(str); } } 

会产生:根派生

一个静态方法存在于一个类的实例之外。 它不能使用任何非静态数据。

一个虚拟方法将被一个重载的函数“覆盖”,这取决于一个实例的types

所以你有一个明确的静态和虚拟的矛盾。

这不是一个支持的问题,这是一个概念。

更新:我在这里certificate是错误的(见评论):

所以我怀疑你会find任何支持虚拟静态方法的OOP语言。

你不疯了。 你所说的是叫Late Late Binding; 它最近被添加到PHP。 有一个伟大的线程描述它 – 在这里: 你什么时候需要使用晚静态绑定?

实际上可以通过使用关键字new而不是virtual将虚拟和静态方法或成员结合起来。

这里是一个例子:

 class Car { public static int TyreCount = 4; public virtual int GetTyreCount() { return TyreCount; } } class Tricar : Car { public static new int TyreCount = 3; public override int GetTyreCount() { return TyreCount; } } ... Car[] cc = new Car[] { new Tricar(), new Car() }; int t0 = cc[0].GetTyreCount(); // t0 == 3 int t1 = cc[1].GetTyreCount(); // t1 == 4 

显然, TyreCount值可以在重写的GetTyreCount方法中设置,但是这样可以避免重复值。 可以从类和类实例中获取值。

现在可以find一个真正智能的使用该function?

有一种方法可以强制抽象generics类的“抽象静态”方法的inheritance。 如下所示:

 public abstract class Mother<T> where T : Mother<T>, new() { public abstract void DoSomething(); public static void Do() { (new T()).DoSomething(); } } public class ChildA : Mother<ChildA> { public override void DoSomething() { /* Your Code */ } } public class ChildB : Mother<ChildB> { public override void DoSomething() { /* Your Code */ } } 

例子(使用以前的母亲):

 public class ChildA : Mother<ChildA> { public override void DoSomething() { Console.WriteLine("42"); } } public class ChildB : Mother<ChildB> { public override void DoSomething() { Console.WriteLine("12"); } } public class Program { static void Main() { ChildA.Do(); //42 ChildB.Do(); //12 Console.ReadKey(); } } 

这不是那么好,因为你只能从一个抽象类inheritance,它会要求你对你的new()实现宽大。

更多的,我认为这将是昂贵的记忆方式取决于你的inheritance类的大小。 如果你有内存问题,你将不得不在新的公共方法之后设置每个属性/variables,这是一个可怕的方法来获得默认值。

我听说delphi支持这样的东西。 看来这是通过使类对象实例的元类来实现的。

我还没有看到它的工作,所以我不知道它的工作原理,或者说有什么意义。

PS请纠正我,如果我错了,因为它不是我的域名。

由于虚拟方法使用已定义types的实例化对象来确定要执行哪个实现(与参考variables的声明types相反)

…和静态,当然,都是关心,如果甚至有一个实例化的类的实例…

所以这些是不相容的。

底线是,如果你想改变一个实例的子类的行为,那么方法应该是基类的虚拟方法,而不是静态方法。

但是,由于您已经有了这些静态方法,现在需要重写它们,您可以通过以下方法解决您的问题:将虚拟实例方法添加到简单委派给静态方法的基类,然后重写这些虚拟实例包装方法(不是静态的)在每个派生的子类,适当的…

沃尔玛用“新”关键字来解决问题。 我真的到了这里,因为我需要这种types的function,Mart的解决scheme工作正常。 事实上,我把它做得更好,并使我的基类方法抽象,迫使程序员提供这个领域。

我的情况如下:

我有一个基类HouseDeed。 每个Housetypes都来自HouseDeed必须有一个价格。

这里是部分基地HouseDeed类:

 public abstract class HouseDeed : Item { public static int m_price = 0; public abstract int Price { get; } /* more impl here */ } 

现在让我们看看两个派生的房子types:

 public class FieldStoneHouseDeed : HouseDeed { public static new int m_price = 43800; public override int Price { get { return m_price; } } /* more impl here */ } 

和…

 public class SmallTowerDeed : HouseDeed { public static new int m_price = 88500; public override int Price { get { return m_price; } } /* more impl here */ } 

正如你所看到的,我可以通过SmallTowerDeed.m_pricetypes和SmallTowerDeed()实例来访问房屋的价格。价格这个机制是抽象的,它让程序员为每个新派生房屋types提供一个价格。

有人指出“静态虚拟”和“虚拟”在概念上是相互矛盾的。 我不同意。 在这个例子中,静态方法不需要访问实例数据,所以要求(1)价格仅通过TYPE可用,并且(2)提供的价格被满足。

重写方法提供了从基类inheritance的成员的新实现。 覆盖声明覆盖的方法称为重写的基本方法。 重写的基本方法必须与重写方法具有相同的签名。 您无法重写非虚拟或静态方法。 重写的基本方法必须是虚拟的,抽象的或重写的。

重写声明不能改变虚拟方法的可访问性。 重写方法和虚方法都必须具有相同的访问级别修饰符。

您不能使用新的,静态的或虚拟的修饰符来修改覆盖方法。

重写属性声明必须指定与inheritance的属性完全相同的访问修饰符,types和名称,并且重写的属性必须是虚拟的,抽象的或重写的。

您可以使用新的关键字

 namespace AspDotNetStorefront { // This Class is need to override StudioOnlineCommonHelper Methods in a branch public class StudioOnlineCommonHelper : StudioOnlineCore.StudioOnlineCommonHelper { // public static new void DoBusinessRulesChecks(Page page) { StudioOnlineCore.StudioOnlineCommonHelper.DoBusinessRulesChecks(page); } } }