C# 为什么实例方法可以';不能称为静态方法
在python中,我可以编写如下代码:C# 为什么实例方法可以';不能称为静态方法,c#,.net,oop,f#,static-methods,C#,.net,Oop,F#,Static Methods,在python中,我可以编写如下代码: class-MyClass: def foo(自我,酒吧): 返回str(self)+bar 定义(自我): 返回“MyClass” a=MyClass() r1=a.foo('1')#MyClass1 r2=MyClass.foo(a,'1')#MyClass1 它将定义MyClass,并允许我使用foo作为静态方法,将实例作为第一个参数传递。由于语言的高度动态性,它可以被执行 但是为什么我不能在.Net语言中使用相同的原则呢 type MyClass
class-MyClass:
def foo(自我,酒吧):
返回str(self)+bar
定义(自我):
返回“MyClass”
a=MyClass()
r1=a.foo('1')#MyClass1
r2=MyClass.foo(a,'1')#MyClass1
它将定义MyClass,并允许我使用foo
作为静态方法,将实例作为第一个参数传递。由于语言的高度动态性,它可以被执行
但是为什么我不能在.Net语言中使用相同的原则呢
type MyClass()=
成员this.Foo bar=this.ToString()+bar
override u.ToString()=“MyClass”
设a=MyClass()
设r1=a.Foo“1”//MyClass1
让r2=MyClass.Foo出现“1”//编译错误
class-MyClass
{
公共字符串Foo(字符串栏)=>this.ToString()+bar;
公共重写字符串ToString()=>“MyClass”;
}
班级计划
{
静态void Main(字符串[]参数)
{
var a=新的MyClass();
var r1=a.Foo(“1”);//MyClass1
var r2=MyClass.Foo(a,“1”);//编译错误
}
}
这个
在编译期间作为第一个参数隐式地传递给任何实例方法,从编译器调用的角度来看,a.Foo(b)
相当于MyClass(a,b)
缺少此功能会导致编写额外的代码来帮助进行类型推断。因此,与其写这封信:
让开始使用任意str(chars:char[])=
chars.Any(String.StartsWith str)
我必须这样写:
让startsWithAny(str:string)(chars:char[])=
任何字符(趣味c->str.StartsWith c)
或者这个:
让开始使用任意str(chars:char[])=
chars.Any(有趣的c->(str:>string).StartsWith c)
更新
由于一些误解,我延长了我的问题
目前,我主要写的是F#,并试图利用每一个功能,包括咖喱,部分应用,等等
函数式风格具有类型推断、清晰、可组合等优点。因此,要使用它们,需要删除所有行为不可预测的代码(虚拟方法调用、重载)
我希望编写如下代码:
让开始使用任意str(chars:char[])=
chars.Any(String.StartsWith str)
//或者更好
//Array.any chars(String.StartsWith str)//理想世界
正如@DmitriTsoy所说,可以通过扩展方法实现:
键入System.String和
静态成员StartsWith((str:string),(char:char))=
str.StartsWith char
但这样的扩展使得不可能使用部分应用程序,并导致使用lambdasfunc->str.StartsWith c
实现扩展的另一种方法:
键入System.String和
静态成员StartsWith(str:string)=
Func(str.StartsWith)
它接受字符串并返回部分应用的StartsWith
。这导致了奇怪的C#call:
chars.Any(c=>String.StartsWith(“someStr”)(c))
但是很好的F#:
chars.Any(String.StartsWith str)
问题:为什么编译器不能将这种静态样式调用转换为实例样式?如果没有找到静态方法,请尝试查找实例方法,并在编译时将调用转换为实例样式。简单的答案是C#就是这样设计的。正如您所说,下面的代码没有编译,因为
Foo
不是静态的,而是因为签名不存在:
var r2 = MyClass.Foo(a, "1"); // Compilation error, the signature Foo(MyClass, string) does not exist
如果我们有一些语法支持,编译器将不得不为每个实例方法添加一个具有以下签名的静态方法:
Foo(MyClass, string) // add an object of the class as a first parameter
但请注意,在C#中,类不能有具有相同签名的静态方法和实例方法
那么,如果作为一名程序员,我想编写一个Foo
实例方法,该方法采用另一个类相同、不同于this
的对象,该怎么办呢?我不能上这样的课:
class MySpecialArray
{
int[] myArray;
void Copy(int number) { /* copy number everywhere in myArray */ }
void Copy(MySpecialArray copied, int number) { /* deep copy of copied's values + number in in myArray */ }
}
答案很简单,C#就是这样设计的。正如您所说,下面的代码没有编译,因为
Foo
不是静态的,而是因为签名不存在:
var r2 = MyClass.Foo(a, "1"); // Compilation error, the signature Foo(MyClass, string) does not exist
如果我们有一些语法支持,编译器将不得不为每个实例方法添加一个具有以下签名的静态方法:
Foo(MyClass, string) // add an object of the class as a first parameter
但请注意,在C#中,类不能有具有相同签名的静态方法和实例方法
那么,如果作为一名程序员,我想编写一个Foo
实例方法,该方法采用另一个类相同、不同于this
的对象,该怎么办呢?我不能上这样的课:
class MySpecialArray
{
int[] myArray;
void Copy(int number) { /* copy number everywhere in myArray */ }
void Copy(MySpecialArray copied, int number) { /* deep copy of copied's values + number in in myArray */ }
}
扩展方法是你所寻找的,它在C++实例中是相同的方法,可以访问<代码>这个< /COD>实例值。但不可能使用类名和实例作为第一个参数的实例方法。C++和C是强类型语言,它们将源代码编译成二进制。它不像Python那样将源代码解析为脚本。您可以像@dmitristoy所说的那样编写扩展方法,但是这些方法缺少OOP继承。静态类只有一个实例。静态项语法的编译器将使用类名而不是实例。这只是编译器的工作方式。在您的示例中,您并没有真正起到任何作用。将参数的类型指定为
string
,与在该参数的每个方法调用中显式指定它有什么区别?你复杂的语言没有任何好处。扩展方法是你正在寻找的是相同的C++实例方法可以访问<代码>这个< /Calp>实例值。但不可能使用类名和实例作为第一个参数的实例方法。C++和C是强类型语言,它们将源代码编译成二进制。它不像Python那样将源代码解析为脚本。您可以将扩展方法编写为@Dmi