C#虚拟静态方法

时间:2009-08-07 09:31:41

标签: c# generics static methods virtual

为什么静态虚拟不可能? C#是依赖还是在OO世界中没有任何意义?

我知道这个概念已被强调,但我没有找到上一个问题的简单答案。

9 个答案:

答案 0 :(得分:51)

virtual表示将在运行时选择调用的方法,具体取决于对象的动态类型。 static表示不需要对象来调用该方法。

你怎么建议用同样的方法做两件事?

答案 1 :(得分:21)

Eric Lippert有一篇关于此事的博客文章,和他的帖子一样,他深入探讨了这个主题:

http://blogs.msdn.com/b/ericlippert/archive/2007/06/14/calling-static-methods-on-type-parameters-is-illegal-part-one.aspx

  

“虚拟”和“静态”是对立的! “virtual”表示“根据运行时类型信息确定要调用的方法”,“static”表示“根据编译时静态分析确定要调用的方法”

答案 2 :(得分:7)

“静态”和“虚拟”之间的矛盾只是一个c#问题。如果“静态”被“班级”取代,就像许多其他语言一样,没有人会被蒙住眼睛。

在这方面,c#的选择太糟糕了c#瘫痪了。仍然可以调用Type.InvokeMember方法来模拟对类级别虚拟方法的调用。您只需将方法名称作为字符串传递。没有编译时检查,没有强类型,也没有子类实现该方法的控制。

一些德尔福美女:

type
  TFormClass = class of TForm;
var
  formClass: TFormClass;
  myForm: TForm;
begin
  ...
  formClass = GetAnyFormClassYouWouldLike;
  myForm = formClass.Create(nil);
  myForm.Show;
end

答案 3 :(得分:7)

那些说静态虚拟方法没有意义的人。如果你不明白这是怎么可能的,那并不意味着它是不可能的。有语言允许这个!!比如说Delphi。

答案 4 :(得分:5)

我将成为那个傻瓜的人。你所描述的并不是技术上语言的一部分。抱歉。但是可以在语言中模拟它

让我们考虑一下你要求的东西 - 你想要一组没有附加到任何特定对象的方法,这些方法在运行时或编译时都可以轻松调用和替换。

听起来像你真正想要的是一个带有委托方法的单例对象。

让我们举个例子:

public interface ICurrencyWriter {
    string Write(int i);
    string Write(float f);
}

public class DelegatedCurrencyWriter : ICurrencyWriter {
    public DelegatedCurrencyWriter()
    {
        IntWriter = i => i.ToString();
        FloatWriter = f => f.ToString();
    }
    public string Write(int i) { return IntWriter(i); }
    public string Write(float f) { return FloatWriter(f); }
    public Func<int, string> IntWriter { get; set; }
    public Func<float, string> FloatWriter { get; set; }
}

public class SingletonCurrencyWriter {
    public static DelegatedCurrencyWriter Writer {
        get {
            if (_writer == null)
               _writer = new DelegatedCurrencyWriter();
            return _writer;
        }
    }
}

正在使用中:

Console.WriteLine(SingletonCurrencyWriter.Writer.Write(400.0f); // 400.0

SingletonCurrencyWriter.Writer.FloatWriter = f => String.Format("{0} bucks and {1} little pennies.", (int)f, (int)(f * 100));

Console.WriteLine(SingletonCurrencyWriter.Writer.Write(400.0f); // 400 bucks and 0 little pennies

鉴于这一切,我们现在有一个单一类写出货币值,我可以改变它的行为。我基本上在编译时定义了行为约定,现在可以在编译时(在构造函数中)或运行时更改行为,也就是说,我相信你试图获得的效果。如果你想要继承行为,可以通过实现反向链接来实现(即,让新方法调用前一个方法)。

那就是说,我不特别推荐上面的示例代码。首先,它不是线程安全的,并且确实没有很多东西可以保持生命健康。全球对这种结构的依赖意味着全球的不稳定。这是在C的昏暗黑暗时期实现可变行为的众多方法之一:函数指针的结构,在这种情况下是单个全局结构。

答案 5 :(得分:2)

虽然从技术上来说无法定义静态虚拟方法,但由于此处已经指出的所有原因,您可以在功能上完成我认为您尝试使用C#扩展方法。

来自MSDN:

  

扩展方法可让您“添加”   没有的现有类型的方法   创建一个新的派生类型,   重新编译或以其他方式修改   原始类型。

查看C# Extension Methods (C# Programming Guide)了解详情。

答案 6 :(得分:2)

是的,这是可能的。

最需要的用例是让工厂可以“覆盖”

为此,您必须使用F-bounded polymorphism依赖泛型类型参数。

示例1 我们来看一个工厂的例子:

class A: { public static A Create(int number) { return ... ;} }
class B: A { /* How to override the static Create method to return B? */}

您还希望可以访问createB并返回B类中的B对象。或者您可能希望A的静态函数成为一个应该可由B扩展的库。解决方案:

class A<T> where T: A<T> { public static T Create(int number) { return ...; } }
class B: A<B>  { /* no create function */ }
B theb = B.Create(2);       // Perfectly fine.
A thea = A.Create(0);       // Here as well

示例2(高级): 让我们定义一个静态函数来乘以值的矩阵。

public abstract class Value<T> where T : Value<T> {
  //This method is static but by subclassing T we can use virtual methods.
  public static Matrix<T> MultiplyMatrix(Matrix<T> m1, Matrix<T> m2) {
    return // Code to multiply two matrices using add and multiply;
  }
  public abstract T multiply(T other);
  public abstract T add(T other);
  public abstract T opposed();
  public T minus(T other) {
    return this.add(other.opposed());
  }
}
// Abstract override
public abstract class Number<T> : Value<T> where T: Number<T> {
  protected double real;

  /// Note: The use of MultiplyMatrix returns a Matrix of Number here.
  public Matrix<T> timesVector(List<T> vector) {
    return MultiplyMatrix(new Matrix<T>() {this as T}, new Matrix<T>(vector));
  }
}
public class ComplexNumber : Number<ComplexNumber> {
  protected double imag;
  /// Note: The use of MultiplyMatrix returns a Matrix of ComplexNumber here.
}

现在您还可以使用静态MultiplyMatrix方法直接从ComplexNumber返回复数矩阵

Matrix<ComplexNumber> result = ComplexNumber.MultiplyMatrix(matrix1, matrix2);

答案 7 :(得分:1)

在.NET中,通过在运行时调用方法时查看对象的实际类型(并从类的vtable中查找最重要的方法)来(粗略地)完成虚方法调度。在调用静态类时,没有要检查的对象实例,因此没有vtable可以进行查找。

答案 8 :(得分:0)

总结所有选项: