C# 静态/实例方法和扩展问题

C# 静态/实例方法和扩展问题,c#,oop,C#,Oop,我是C#新手,我开始从事一个项目,该项目需要在C#中的类中添加一个方法。我发现自己正在重新检查静态方法和实例方法之间的差异,无法在示例项目中解释以下内容 我的核心目标: namespace ExtendingObjects { public class MyCoreObject { public String name; public String returnName() { return name;

我是C#新手,我开始从事一个项目,该项目需要在C#中的类中添加一个方法。我发现自己正在重新检查静态方法和实例方法之间的差异,无法在示例项目中解释以下内容

我的核心目标:

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()
,这是非常不同的。