Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么实例方法可以';不能称为静态方法_C#_.net_Oop_F#_Static Methods - Fatal编程技术网

C# 为什么实例方法可以';不能称为静态方法

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

在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()=
成员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
但这样的扩展使得不可能使用部分应用程序,并导致使用lambdas
func->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