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
C# virtual static method
提问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
virtual
means the method called will be chosen at run-time, depending on the dynamic type of the object. static
means 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) 有一篇关于此的博客文章,和往常一样,他的文章深入探讨了这个主题:
“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 createB
to 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 MultiplyMatrix
method 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:
总结所有提供的选项:
This is not a part of C# because in it,
static
means "not bound to anything at runtime"as it has ever since C (and maybe earlier).static
entities arebound to the declaring type (thus are able to access its otherstatic
entities), but only at compile time.- This is possible in other languages where a
static
equivalent (if needed at all) means "bound to a type object at runtime"instead. Examples include Delphi, Python, PHP.
- This is possible in other languages where a
This can be emulated in a number of ways which can be classified as:
- Use runtime binding
- Static methods with a singleton objector lookalike
- Virtual method that returns the same for all instances
- Redefined in a derived type to return a different result (constant or derived from static members of the redefining type)
- Retrieves the type object from the instance
- Use compile-time binding
- Use runtime binding
这不是 C# 的一部分,因为它的
static
意思是“在运行时不绑定任何东西”,因为它自 C 以来(可能更早)。static
实体被结合到声明类型(从而能够访问它的其他static
实体),但只有在编译时。- 这在其他语言中
static
是可能的,其中等效的(如果需要的话)意味着“在运行时绑定到类型对象”。示例包括 Delphi、Python、PHP。
- 这在其他语言中
这可以通过多种方式进行模拟,这些方式可以分为:
- 使用运行时绑定
- 具有单例对象或相似对象的静态方法
- 对所有实例返回相同的虚拟方法
- 在派生类型中重新定义以返回不同的结果(常量或派生自重新定义类型的静态成员)
- 从实例中检索类型对象
- 使用编译时绑定
- 使用运行时绑定