C# 编译器:无法在非静态上下文中访问静态方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/809550/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 02:05:49  来源:igfitidea点击:

C# Compiler : cannot access static method in a non-static context

c#

提问by Surf-O-Matic

I have the code below :

我有下面的代码:

public class Anything
{
    public int Data { get; set;}
}

public class MyGenericBase<T>
{
    public void InstanceMethod(T data)
    {
        // do some job
    }

    public static void StaticMethod(T data)
    {
        // do some job
    }

    // others members...
}

public sealed class UsefulController : MyGenericBase<Anything>
{
    public void ProxyToStaticMethod()
    {
        StaticMethod(null);
    }

    // others non derived members...
}

public class Container
{
    public UsefulController B { get; set; }
}

public class Demo
{
    public static void Test()
    {
        var c = new Container();
        c.B.InstanceMethod(null);   // Works as expected.
        c.B.StaticMethod(null);     // Doesn't work. 
                                    // Static method call on object rather than type. 
                                    // How to get the static method on the base type ?
        c.B.ProxyToStaticMethod();  // Works as expected.
    }
}

The compiler is very angry... I understand the error message but I don't know how to solve this. I was trying to get a type rather than an object to make my static method call, but I don't find the way to do it correctly. Moreover this results in something not elegant at all.

编译器很生气...我明白错误信息但我不知道如何解决这个问题。我试图获得一个类型而不是一个对象来进行我的静态方法调用,但我没有找到正确的方法。此外,这会导致根本不优雅的东西。

Basically, the GenericBase is a class from a framework with a lot of static methods and some instance methods. The controller is typing this class and extending it.

基本上,GenericBase 是来自框架的类,具有许多静态方法和一些实例方法。控制器正在输入这个类并扩展它。

The container is a group of logical related controllers.

容器是一组逻辑相关的控制器。

Interesting thing : a Java version of this code compiles correctly, but with a warning. The execution is correct, too.

有趣的是:此代码的 Java 版本可以正确编译,但有警告。执行也是正确的。

Does it exist a design pattern to solve this ?

是否存在解决此问题的设计模式?

Thanks for your inputs !

感谢您的投入!



I found a way to get rid of this problem, thanks to your answers. It seems to work, but I can not tell if there are side effects right know.

由于您的回答,我找到了解决此问题的方法。它似乎有效,但我不知道是否有副作用对吧。

    public class GenericBase<T> : MyGenericBase<T>
{
    // Create instance calls here for every base static method.
}

public sealed class UsefulController : GenericBase<Anything>
{
    // others non derived members...
}

采纳答案by Lasse V. Karlsen

A call to a static method will be compiled to call a specific static method on a specific class. In other words, it won't use the contents of B to determine which static method to call.

对静态方法的调用将被编译为调用特定类上的特定静态方法。换句话说,它不会使用 B 的内容来确定调用哪个静态方法。

So the call has to be resolvable at compile time, hence it complains, because for all it knows, you could replace the contents of that property with multiple concrete types, which would mean that the call to the static method would have to be resolved to a static method in either of these classes.

因此调用必须在编译时可解析,因此它会抱怨,因为就它所知,您可以用多个具体类型替换该属性的内容,这意味着对静态方法的调用必须解析为这些类中的任何一个中的静态方法。

The compiler does not have anything like a virtual or abstract static method, so for one you can't guarantee that all of those classes have that static method. And since the call has to be resolvable at compile time, it won't work like that.

编译器没有任何类似于虚拟或抽象静态方法的东西,因此对于一个,您不能保证所有这些类都具有该静态方法。而且由于调用必须在编译时可解析,因此它不会像那样工作。

You can, as you've noticed, call an instance method of the object, which in turn calls the static method. This does not invalidate the above rules since when the compiler compiles that instance method, which static method it will call is constant and known.

正如您所注意到的,您可以调用对象的实例方法,该方法又调用静态方法。这不会使上述规则无效,因为当编译器编译该实例方法时,它将调用的静态方法是常量和已知的。

回答by Mehrdad Afshari

You can't do this in C#. You can do it in VB.NET and Java, but honestly, it doesn't really make sense. It just gives you a false sense of polymorphism in a staticmethod, which is not real by any means. Since it's not polymorphic, the whole method call is known at compile time (statically) and you could mention the call directly with the class name.

你不能在 C# 中做到这一点。你可以在 VB.NET 和 Java 中做到这一点,但老实说,这并没有什么意义。它只是给你一种static方法中多态的错误感觉,这绝不是真实的。由于它不是多态的,整个方法调用在编译时(静态)是已知的,您可以直接使用类名提及调用。

回答by tvanfosson

To call the static method you need to refer to it from the class it's defined in, not an instance of that class.

要调用静态方法,您需要从定义它的类中引用它,而不是从该类的实例中引用它。

 MyGenericBase<Anything>.StaticMethod( null );

回答by Lucero

You can do one of those:

您可以执行以下操作之一:

UsefulController.StaticMethod(null);  
MyGenericBase<Anything>.StaticMethod(null);  

Using the instance is not possible, as already explained by others.

正如其他人已经解释的那样,使用该实例是不可能的。

回答by John Bosco

Since it is 9 years ago, I know it is way too many years ago. I go ahead and practiced C# without caring rl implementation. I think that your post has no goal in doing inheritance, OOAD, nor encapsulation (info hiding).

既然是 9 年前的事,我知道那是太多年前的事了。我继续练习 C# 而不关心 rl 实现。我认为您的帖子没有进行继承、OOAD 或封装(信息隐藏)的目标。

From your code to my code here.

从你的代码到我的代码在这里。

public class Anything
{
    private int data, data2; //field

    public Anything()
    {
        data = default(int);
    }
    public int Data { get; set; }
}

public class GenericParentClass<T>
{
    public static void StaticMethod(T data)
    {
        // do some job
    }

    public void InstanceMethod(T data)
    {
        // do some job
    }
}

public sealed class UsefulController<T> : GenericParentClass<T> where  T : Anything, new()
{
    //all static public methods must be placed before all non-static public methods. [StyleCop Rule: SA1204]
    public static new void StaticMethod(T data)  //'UsefulController'.StaticMethod(Anything) hides inherited member 'GenericParentClass<Anything>.StaticMethod(Anything)'. Use the new keyword if hiding was intended.
    {
        GenericParentClass<T>.StaticMethod(data);  //'data' is a variable but used like a type //arugement type T is not assignable to parameter type 'data'.
    }

    public void EncapsulatedStaticMethod()
    {
        T @class = new T(); //cannot create an instance of the variable type T because it does not have the new() constraint. //T is type and @class is variable and new is an instance.
        StaticMethod(@class);  
    }

    public void EncapsulatedInstanceMethod(T data)
    {
        base.InstanceMethod(data);
    }
}

public class Container
{
    public UsefulController<Anything>  B { get; set; }
}

public class Testing   
{
    public static void Main()
    {
        Anything @var = new Anything();
        var c = new Container();
        c.B.InstanceMethod(null);   
        c.B.EncapsulatedStaticMethod();    
        c.B.EncapsulatedInstanceMethod(var);  
    }
}