Surf-O-Matic
Surf-O-Matic

Reputation: 343

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

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.

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.

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...
}

Upvotes: 34

Views: 107747

Answers (5)

John Bosco
John Bosco

Reputation: 1

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).

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);  
    }
}

Upvotes: -3

Lucero
Lucero

Reputation: 60190

You can do one of those:

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

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

Upvotes: 1

tvanfosson
tvanfosson

Reputation: 532465

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 );

Upvotes: 14

Mehrdad Afshari
Mehrdad Afshari

Reputation: 421988

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 static method, 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.

Upvotes: 4

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391336

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.

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.

Upvotes: 35

Related Questions