对象中静态方法和非静态方法的区别
Difference between static methods and nonstatic methods in object
我目前正在通过德语书籍 "Schrödinger Programmiert C#" 学习使用 C# 语言进行编程,第 156 页有一个代码示例。问题是:我不明白为什么我在第二种方法中使用静态而不是第一种方法。
人class
class Person
{
public string Name { get; set; }
public float WalkedKm
{
get
{
return this.Footsteps * 0.75f / 1000.0f;
}
}
public float Weight { get; set; }
public int Footsteps { get; private set; }
public void Walk (int Footsteps)
{
if (Footsteps > -1)
this.Footsteps += Footsteps;
}
public static float AverageWalkedKm(Person[] persons)
{
int amount = persons.Length;
float walkSum = 0;
foreach (Person p in persons)
walkSum += p.WalkedKm;
return walkSum / (float)amount;
}
}
在主要方法中
Person p1 = new Person();
Person p2 = new Person();
p1.Name = "Schrödinger";
p2.Name = "Schrödingers Girlfriend";
p1.Walk(1500);
p2.Walk(1500);
p2.Walk(2100);
Person[] person = new Person[] { p1, p2 };
Console.WriteLine("Schrödingers steps: {0}. km {1}", p1.Footsteps, p1.WalkedKm);
Console.WriteLine("Her steps: {0}. km {1}", p2.Footsteps, p2.WalkedKm);
float average = Person.AverageWalkedKm(person);
Console.WriteLine("Average: {0}km", average);
Console.ReadKey();
请帮我理解其中的区别!
因为您使用的是 Footsteps 变量,它不是静态的
float AverageWalkedKm(Person[] persons)
可以是静态的,因为它不会尝试访问 class 的任何 实例 成员(字段、属性或方法)。 =19=]
void Walk (int Footsteps)
不能是静态的,因为它确实访问 class 的 实例 成员。 (即 Footsteps
属性。)
注意:实例成员=非静态成员。
编辑
因此,您反对 AverageWalkedKm()
中的 Person[] persons
参数的数据类型为 Person
,因此在您看来它正在访问实例成员。
嗯,是的,它正在访问实例成员,但不是它自己的实例。它被赋予了与之一起工作的实例。所以,这个方法可能属于一个完全不同的 class,并且它仍然可以工作,没有变化,因为它被赋予 Person
的实例来调用。当我们说实例方法能够访问实例成员时,我们指的是 它自己的实例 ,如 this.member
,甚至没有 this.
,因为它是可选的。
当您不需要(或不想)需要 class 的对象实例时,您可以使用静态方法。在您的示例中,无论是否创建了 Person class 的对象实例,您都可以调用 Person.AverageWalkedKm 方法。但是,因为 Walk 方法引用一个实例变量 (Footsteps),它不能是静态的:您必须首先创建 Person class 的实例(您的示例中的 p1 和 p2),然后使用这些实例以便调用步行方法。
我目前正在通过德语书籍 "Schrödinger Programmiert C#" 学习使用 C# 语言进行编程,第 156 页有一个代码示例。问题是:我不明白为什么我在第二种方法中使用静态而不是第一种方法。
人class
class Person
{
public string Name { get; set; }
public float WalkedKm
{
get
{
return this.Footsteps * 0.75f / 1000.0f;
}
}
public float Weight { get; set; }
public int Footsteps { get; private set; }
public void Walk (int Footsteps)
{
if (Footsteps > -1)
this.Footsteps += Footsteps;
}
public static float AverageWalkedKm(Person[] persons)
{
int amount = persons.Length;
float walkSum = 0;
foreach (Person p in persons)
walkSum += p.WalkedKm;
return walkSum / (float)amount;
}
}
在主要方法中
Person p1 = new Person();
Person p2 = new Person();
p1.Name = "Schrödinger";
p2.Name = "Schrödingers Girlfriend";
p1.Walk(1500);
p2.Walk(1500);
p2.Walk(2100);
Person[] person = new Person[] { p1, p2 };
Console.WriteLine("Schrödingers steps: {0}. km {1}", p1.Footsteps, p1.WalkedKm);
Console.WriteLine("Her steps: {0}. km {1}", p2.Footsteps, p2.WalkedKm);
float average = Person.AverageWalkedKm(person);
Console.WriteLine("Average: {0}km", average);
Console.ReadKey();
请帮我理解其中的区别!
因为您使用的是 Footsteps 变量,它不是静态的
float AverageWalkedKm(Person[] persons)
可以是静态的,因为它不会尝试访问 class 的任何 实例 成员(字段、属性或方法)。 =19=]
void Walk (int Footsteps)
不能是静态的,因为它确实访问 class 的 实例 成员。 (即 Footsteps
属性。)
注意:实例成员=非静态成员。
编辑
因此,您反对 AverageWalkedKm()
中的 Person[] persons
参数的数据类型为 Person
,因此在您看来它正在访问实例成员。
嗯,是的,它正在访问实例成员,但不是它自己的实例。它被赋予了与之一起工作的实例。所以,这个方法可能属于一个完全不同的 class,并且它仍然可以工作,没有变化,因为它被赋予 Person
的实例来调用。当我们说实例方法能够访问实例成员时,我们指的是 它自己的实例 ,如 this.member
,甚至没有 this.
,因为它是可选的。
当您不需要(或不想)需要 class 的对象实例时,您可以使用静态方法。在您的示例中,无论是否创建了 Person class 的对象实例,您都可以调用 Person.AverageWalkedKm 方法。但是,因为 Walk 方法引用一个实例变量 (Footsteps),它不能是静态的:您必须首先创建 Person class 的实例(您的示例中的 p1 和 p2),然后使用这些实例以便调用步行方法。