C#虚拟静态方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1243836/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 14:08:27  来源:igfitidea点击:

C# virtual static method

c#genericsstaticmethodsvirtual

提问by Toto

Why is static virtual impossible? Is C# dependent or just don't have any sense in the OO world?

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

I know the concept has already been underlined but I did not find a simple answer to the previous question.

我知道这个概念已经被划线了,但我没有找到对上一个问题的简单答案。

采纳答案by sbi

virtualmeans the method called will be chosen at run-time, depending on the dynamic type of the object. staticmeans no object is necessary to call the method.

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

How do you propose to do both in the same method?

您如何建议以相同的方法同时进行?

回答by thecoop

In .NET, virtual method dispatch is (roughly) done by looking at the actual type of an object when the method is called at runtime, and finding the most overriding method from the class's vtable. When calling on a static class, there is no object instance to check, and so no vtable to do the lookup on.

在 .NET 中,虚拟方法分派(大致)是通过在运行时调用方法时查看对象的实际类型并从类的 vtable 中找到最重载的方法来完成的。调用静态类时,没有要检查的对象实例,因此没有要查找的 vtable。

回答by Michael Stum

Eric Lippert has a blog post about this, and as usual with his posts, he covers the subject in great depth:

埃里克·利珀特 (Eric Lippert) 有一篇关于此的博客文章,和往常一样,他的文章深入探讨了这个主题:

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

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

“virtual” and “static” are opposites! “virtual” means “determine the method to be called based on run time type information”, and “static” means “determine the method to be called solely based on compile time static analysis”

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

回答by Zach Bonham

While technically its not possible to define a static virtualmethod, for all the reasons already pointed out here, you can functionally accomplish what I think your trying using C# extension methods.

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

From MSDN:

来自 MSDN:

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type.

扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。

Check out C# Extension Methods (C# Programming Guide)for more details.

查看C# 扩展方法(C# 编程指南)了解更多详细信息。

回答by plinth

I'm going to be the one who naysays. What you are describing is not technically part of the language. Sorry. But it is possible to simulate itwithin the language.

我将成为反对者。您所描述的内容在技术上不是语言的一部分。对不起。但是可以在语言中模拟它

Let's consider what you're asking for - you want a collection of methods that aren't attached to any particular object that can all be easily callable and replaceable at run time or compile time.

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

To me that sounds like what you really want is a singleton object with delegated methods.

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

Let's put together an example:

让我们举一个例子:

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;
        }
    }
}

in use:

正在使用:

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

Given all this, we now have a singleton class that writes out currency values and I can change the behavior of it. I've basically defined the behavior conventionat compile time and can now change the behavior at either compile time (in the constructor) or run time, which is, I believe the effect you're trying to get. If you want inheritance of behavior, you can do that to by implementing back chaining (ie, have the new method call the previous one).

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

That said, I don't especially recommend the example code above. For one, it isn't thread safe and there really isn't a lot in place to keep life sane. Global dependence on this kind of structure means global instability. This is one of the many ways that changeable behavior was implemented in the dim dark days of C: structs of function pointers, and in this case a single global struct.

也就是说,我并不特别推荐上面的示例代码。一方面,它不是线程安全的,而且真的没有很多地方可以让生活保持清醒。全球对这种结构的依赖意味着全球不稳定。这是在 C 的黑暗时代实现可变行为的众多方式之一:函数指针结构,在这种情况下是单个全局结构。

回答by Johan Nilsson

The contradiction between "static" and "virtual" is only a c# problem. If "static" were replaced by "class level", like in many other languages, no one would be blindfolded.

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

Too bad the choice of words made c# crippled in this respect. It is still possible to call the Type.InvokeMember method to simulate a call to a class level, virtual method. You just have to pass the method name as a string. No compile time check, no strong typing and no control that subclasses implement the method.

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

Some Delphi beauty:

一些德尔福之美:

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

回答by Sergey Krusch

Guys who say that there is no sense in static virtual methods. If you don't understand how this could be possible, it does not means that it is impossible. There are languages that allow this!! Look at Delphi, for example.

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

回答by Mika?l Mayer

Yes it is possible.

对的,这是可能的。

The most wanted use case for that is to have factorieswhich can be "overriden"

最想要的用例是拥有可以“覆盖”的工厂

In order to do this, you will have to rely on generic type parameters using the F-bounded polymorphism.

为了做到这一点,您将不得不依赖使用F-bounded polymorphism 的泛型类型参数。

Example 1Let's take a factory example:

示例 1让我们以工厂示例为例:

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

You also want createBto be accessible and returning B objects in the B class. Or you might like A's static functions to be a library that should be extensible by B. Solution:

您还希望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

Example 2 (advanced):Let's define a static function to multiply matrices of values.

示例 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.
}

Now you can also use the static MultiplyMatrixmethod to return a matrix of complex numbers directly from ComplexNumber

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

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

回答by ivan_pozdeev

To summarize all the options presented:

总结所有提供的选项: