C# “C”;继承;静态方法?

C# “C”;继承;静态方法?,c#,inheritance,static-methods,C#,Inheritance,Static Methods,下面是我想要完成的一个例子: abstract class DoSomething { static void DoWhateverItIsThatIDo() { Console.WriteLine("You asked the abstract class to work. Too bad."); } } class InspireMe : DoSomething { static void DoWhateverItIsThatIDo()

下面是我想要完成的一个例子:

abstract class DoSomething
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You asked the abstract class to work. Too bad.");
    }
}

class InspireMe : DoSomething
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You are amazing.");
    }
}

class InsultMe : DoSomething
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You aren't worth it.");
    }
}

class Program
{
    static void Main()
    {
        DoSomething worker = InsultMe;
        worker.DoWhateverItIsThatIDo(); 

        worker = InspireMe;
        worker.DoWhateverItIsThatIDo();
    }
}
我来自Python的背景,方法本身可以是变量,然后可以调用它。看起来C#没有这个概念,但我正试图实现类似的目标

这个想法是我想要一个抽象类型的变量,这样许多不同类型的子类型可以存在其中。所有这些子类型都有特定的方法。我希望能够将这些子类型中的任何一个分配给这个抽象类型的变量,然后调用子类型中存在的静态方法

在C#术语中,我希望能够将类分配给变量,而不是类的实例,然后调用该类的静态方法

工厂听起来可能是在正确的路径上,但我不确定工厂本身如何能够生成对类的这些引用(而不是创建实例)

我可以修改它以使用实例,但是假设我想要生成每种类型的类的静态方法,所有这些类仍然从基类型继承


我觉得很有可能有一种方法可以做到这一点——有人能给我一个建议吗?

在C中,你不能用类作为变量,正如你所描述的那样。反射本质上允许您将类型视为变量,并动态地调用它们的静态成员,但这将是混乱的,并且不是类型安全的

通过使用singleton模式,您基本上可以完成您想要做的事情:

interface IDoSomething
{
    void DoWhateverItIsThatIDo();
}

class DoSomething : IDoSomething
{
    private DoSomething() {}
    internal static readonly IDoSomething Instance;
    static DoSomething()
    {
        Instance = new DoSomething();
    }

    public void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You asked the abstract class to work. Too bad.");
    }
}

class InspireMe : IDoSomething
{
    private InspireMe() {}
    internal static readonly IDoSomething Instance;
    static InspireMe()
    {
        Instance = new InspireMe();
    }

    public void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You are amazing.");
    }
}

class InsultMe : IDoSomething
{
    private InsultMe() {}
    internal static readonly IDoSomething Instance;
    static InsultMe()
    {
        Instance = new InsultMe();
    }

    public void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You aren't worth it.");
    }
}
C#和Java都不能让您重写静态基类方法

但是,您似乎正在使用对对象的引用(您的
worker
变量),所以为什么不使用非静态类方法呢


(如果这不是你想要做的,请澄清。)

我不是100%确定这是你想要的,但我写了一个模拟的库


当然,这需要大量使用
dynamic
关键字,这可能没有什么用处,因为您会丢失大量编译时检查。

除了类和实例之外,您真正想要的是对具有特定签名的方法的引用,在您的例子中是
void()

虽然不能将静态类分配给变量,但可以以类型安全的方式将方法分配给变量。在C#中,通常会使用or重载,具体取决于方法签名的外观

为了使这一点更有趣,假设您想要引用类似于
intfoo(string,bool)
的内容,只需使用
Func
类型的变量,并将具有此签名的任何方法分配给它即可

解决问题的代码大致如下所示:

class DoSomething
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You asked the abstract class to work. Too bad.");
    }
}

class InspireMe
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You are amazing.");
    }
}

class InsultMe
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You aren't worth it.");
    }
}

class Program
{
    static void Main()
    {
        Action worker = InsultMe.DoWhateverItIsThatIDo;
        worker(); 

        worker = InspireMe.DoWhateverItIsThatIDo;
        worker();
    }
}

解决方法可能是在基本抽象类中声明类型为
Action
的属性,该属性保存要调用的方法。然后在派生类实例化期间通过调用基类构造函数初始化此属性:

abstract class DoSomething
{
    public Action DoWhateverItIsThatIDo { get; set; }

    protected DoSomething() { DoWhateverItIsThatIDo = DoSomething.DoIt; }

    protected DoSomething(Action whatAction)
    {
        DoWhateverItIsThatIDo = whatAction;
    }

    protected static void DoIt()
    {
        Console.WriteLine("You asked the abstract class to work. Too bad.");
    }
}

class InspireMe : DoSomething
{
    public InspireMe() : base(InspireMe.DoIt) { }

    private static void DoIt()
    {
        Console.WriteLine("You are amazing.");
    }
}

class InsultMe : DoSomething
{
    public InsultMe() : base(InsultMe.DoIt) { }

    private static void DoIt()
    {
        Console.WriteLine("You aren't worth it.");
    }
}

class DoWhatBaseClassDoes : DoSomething
{
    public DoWhatBaseClassDoes() : base() {}
}

class Program
{
    static void Main(string[] args)
    {
        DoSomething worker = new InsultMe();
        worker.DoWhateverItIsThatIDo();

        worker = new InspireMe();
        worker.DoWhateverItIsThatIDo();

        // In this case base class method is invoked
        worker = new DoWhatBaseClassDoes();
        worker.DoWhateverItIsThatIDo();
    }
} 

从某种意义上说,一个方法可以是一个变量:
Action workerMethod=InspireMe.DoWhateverItIsThatIDo;工作方法()?不完全是你写的,但是如果你想要一个实际的
工作者
对象,你可以调用多个方法,那么你不应该使用静态方法;派生类型没有要调用的基类型的构造函数(唯一的构造函数是私有的),因此不会编译。如果您确实向它们公开了一个构造函数,那么类型就不会是单例的,因为您创建了多个类型实例和所有实例。@Servy我在示例中没有看到任何派生类,只是接口实现,因此没有编译问题。@Servy很抱歉,您不得不批评我的半生不熟的代码。我现在已经验证了它的编译和工作符合预期。我认为没有任何理由使用单例或静态代码。静态代码无论如何都不适合生成。没有注射就无法测试。他似乎不懂c#IMO。。。因为所需要的只是接口,最多是一个带有虚方法的抽象类。@phillip似乎OP需要一些适合某个接口的静态对象。对于单例模式来说,这不是一个很好的用例吗?代码的
静态部分实际上做的不多。只需调用一个空构造函数并将其分配给一个字段。你们可以得到我的投票,但问题是。。。我以为他想要DoSomething.DoWhateverItIsThatIDo()作为默认方法,如果它不存在于InspireMe或Imprime中就会被调用。。。也许我错了-我们会明白的。不编译-
侮辱我
InspireMe
是类型,而不是
Action
s-这应该是
Action worker=侮辱我然后
worker()。您可能还需要向这些静态方法添加一个
public
修饰符谢谢Pieter,修好了这是个不错的密码员。。。感觉非常javascript(ish)…:这看起来比应该的麻烦多了,但我想它完成了任务+1.
class DoSomething
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You asked the abstract class to work. Too bad.");
    }
}

class InspireMe
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You are amazing.");
    }
}

class InsultMe
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You aren't worth it.");
    }
}

class Program
{
    static void Main()
    {
        Action worker = InsultMe.DoWhateverItIsThatIDo;
        worker(); 

        worker = InspireMe.DoWhateverItIsThatIDo;
        worker();
    }
}
abstract class DoSomething
{
    public Action DoWhateverItIsThatIDo { get; set; }

    protected DoSomething() { DoWhateverItIsThatIDo = DoSomething.DoIt; }

    protected DoSomething(Action whatAction)
    {
        DoWhateverItIsThatIDo = whatAction;
    }

    protected static void DoIt()
    {
        Console.WriteLine("You asked the abstract class to work. Too bad.");
    }
}

class InspireMe : DoSomething
{
    public InspireMe() : base(InspireMe.DoIt) { }

    private static void DoIt()
    {
        Console.WriteLine("You are amazing.");
    }
}

class InsultMe : DoSomething
{
    public InsultMe() : base(InsultMe.DoIt) { }

    private static void DoIt()
    {
        Console.WriteLine("You aren't worth it.");
    }
}

class DoWhatBaseClassDoes : DoSomething
{
    public DoWhatBaseClassDoes() : base() {}
}

class Program
{
    static void Main(string[] args)
    {
        DoSomething worker = new InsultMe();
        worker.DoWhateverItIsThatIDo();

        worker = new InspireMe();
        worker.DoWhateverItIsThatIDo();

        // In this case base class method is invoked
        worker = new DoWhatBaseClassDoes();
        worker.DoWhateverItIsThatIDo();
    }
}