C# 静态/实例方法和扩展问题
我是C#新手,我开始从事一个项目,该项目需要在C#中的类中添加一个方法。我发现自己正在重新检查静态方法和实例方法之间的差异,无法在示例项目中解释以下内容 我的核心目标:C# 静态/实例方法和扩展问题,c#,oop,C#,Oop,我是C#新手,我开始从事一个项目,该项目需要在C#中的类中添加一个方法。我发现自己正在重新检查静态方法和实例方法之间的差异,无法在示例项目中解释以下内容 我的核心目标: namespace ExtendingObjects { public class MyCoreObject { public String name; public String returnName() { return name;
namespace ExtendingObjects
{
public class MyCoreObject
{
public String name;
public String returnName()
{
return name;
}
}
}
我尝试扩展对象:
namespace ExtendingObjects
{
public static class Extensions
{
public static void addName(this MyCoreObject mco, String str)
{
mco.name=str;
}
public static String getName(this MyCoreObject mco)
{
return "test";
}
}
}
呼叫程序:
namespace ExtendingObjects
{
class Program
{
static void Main(string[] args)
{
MyCoreObject co = new MyCoreObject();
co.addName("test");
//Static method seems to work with instance?
String n = co.returnName();
Console.WriteLine("The name is " + n);
Console.ReadLine();
//Does not work
//Static method from a type
//String n2 = MyCoreObject.getName()
}
}
}
据我所知,静态项保留在类中,而实例项保留在每个实例中。然而,我似乎能够通过上面的实例访问静态方法,但无法通过类型访问静态方法
为什么co.returnName()有效,而mycorObject.getName()无效?根据我的阅读,我认为它们是相反的。如何在不先实例化对象的情况下使getName()方法可用
提前感谢。您的两个方法都是扩展方法,它们在被调用时看起来像实例方法。它们可以静态调用,但您需要提供实例作为第一个参数,并指定声明扩展方法的类,而不是方法“扩展”的类型:
当您将扩展方法“作为”实例方法调用时,这只是一个编译器技巧。所以这个代码:
co.addName("test");
被编译为与以下内容完全等效:
Extensions.addName(co, "test");
(顺便说一句,你最好尽快开始遵循常规。你养成的习惯越早越好。)你的两个方法都是扩展方法,它们在被调用时看起来像实例方法。它们可以静态调用,但您需要提供实例作为第一个参数,并指定声明扩展方法的类,而不是方法“扩展”的类型:
当您将扩展方法“作为”实例方法调用时,这只是一个编译器技巧。所以这个代码:
co.addName("test");
被编译为与以下内容完全等效:
Extensions.addName(co, "test");
(顺便说一句,你最好尽快开始遵循常规。你养成的习惯越早越好。)扩展方法确实是静态的,但它在实例上运行。当您编码
此mycorObject mco
时,您接受一个参数,该参数是要在其上改变状态的对象实例。我愿意回答,但我想不出如何简单地解释这一点。@TimSchmelter:不,你不能用C#来解释——谢天谢地。你可以用Java编程,这是一个严重的错误。如果您看到someThread.sleep(100)
,它看起来像是在告诉某个特定的线程睡觉,而实际上它总是当前正在执行的线程。@JonSkeet:是的,我最近在VB.NET中编写了太多代码。据我记忆所及,它在java中也是有效的。在C中,只能使用ClassName.StaticMethod()
或(如果它在类中)StaticMethod()
。在VB.NET或java中,只会收到警告。扩展方法确实是静态的,但它在实例上运行。当您编码此mycorObject mco
时,您接受一个参数,该参数是要在其上改变状态的对象实例。我愿意回答,但我想不出如何简单地解释这一点。@TimSchmelter:不,你不能用C#来解释——谢天谢地。你可以用Java编程,这是一个严重的错误。如果您看到someThread.sleep(100)
,它看起来像是在告诉某个特定的线程睡觉,而实际上它总是当前正在执行的线程。@JonSkeet:是的,我最近在VB.NET中编写了太多代码。据我记忆所及,它在java中也是有效的。在C中,只能使用ClassName.StaticMethod()
或(如果它在类中)StaticMethod()
。在VB.NET或java中,您只会收到警告。Jon,感谢您的快速响应,您的方法肯定有效。但是,是否可以重写我的扩展,使其像MyObject.getName()一样工作?我正在试图弄清楚为什么它的行为与我在其他示例中看到的不一样,例如,@Trebor:不,你不能扩展你可以在类型上作为静态方法调用的方法集。抱歉,太密集了。为什么要执行以下操作:公共静态类StringExtension{public static int WordCount(this String str){return str.Split(new char[]{'','.','?'},StringSplitOptions.RemoveEmptyEntries)。Length;}@Trebor:No,s
大概是对字符串的引用-因此它被编译为StringExtension.WordCount
@Trebor:您可以这样做。这不是你问题中被注释掉的那一行-你尝试了mycorobject.getName()
,这是非常不同的。Jon,谢谢你的快速回复,你的方法肯定有效。但是,是否可以重写我的扩展,使其像MyObject.getName()一样工作?我正在试图弄清楚为什么它的行为与我在其他示例中看到的不一样,例如,@Trebor:不,你不能扩展你可以在类型上作为静态方法调用的方法集。抱歉,太密集了。为什么要执行以下操作:公共静态类StringExtension{public static int WordCount(this String str){return str.Split(new char[]{'','.','?'},StringSplitOptions.RemoveEmptyEntries)。Length;}@Trebor:No,s
大概是对字符串的引用-因此它被编译为StringExtension.WordCount
@Trebor:您可以这样做。这不是你问题中被注释掉的那一行-你尝试了mycorobject.getName()
,这是非常不同的。