简体   繁体   中英

C#: “Cannot create an instance of the static class”

I'm in the process of converting some Java code to C# and stumbled across the following curious thing:

public interface IActivation {
    public abstract double func(double inputput);

    public static class S1 : IActivation {
        public double func(double input) {
            if (input > 0) return 1.0;
            return 0.0;
        }
    }
}

SomewhereElse (usage):

protected IActivation activation = new IActivation.S1();

Looking at the original code, it's clear what the intention of this was:

  1. Declare an interface and nested within it several static implementations of that interface (the code contains other implementations of IActivation, eg "S2", "S3" etc. which were omitted here).
  2. The typical usage scenario for this was to assign a variable to one specific implementation of that interface. Also, by the way you'd need to instantiate that variable, it's perfectly clear where those specific implementations belong to - in a manner of speaking, the nested declaration would further increase the readability of the code (eg new IActivation.S1(); makes it clear that S1 is a specific implementation of IActivation).

Interestingly, C# does not like the way the whole thing is defined: " Cannot create an instance of the static class 'IActivation.S1 ". Does anyone know a way of how to refactor that code so that 1. and 2. would be preserved?

In Java, a static inner class has no implicit access to the members of its enclosing type. In C#, all nested types have no such access to their parent type's members; there is no modifier you need to add in C# to trigger this behavior.

In C#, static classes are abstract sealed , so they cannot be created nor derived -- this is not the same meaning as in Java. Additionally, interfaces cannot contain type declarations of their own.

Try something like this:

public interface IActivation {
    double Func(double inputput);
}

public class S1 : IActivation {
    public static readonly S1 Instance = new S1();

    private S1() { }

    public double Func(double input) {
        if (input > 0) return 1.0;
        return 0.0;
    }
}

If your goal is to provide default implementations in some "readable" way (though I dispute that IActivator.S1() is inherently more readable...) then you could create a static factory class:

public static class Activator
{
    public static S1 S1
    {
        get
        {
            return S1.Instance;

            // Or you could do this if you make the S1 constructor public:
            // return new S1();
        }
    }
}

However, I dispute the claim that this is more readable or helpful. Visual Studio will, when constructing an object in the context of a particular type, display all of that type's subtypes. So if you do this ( | represents the cursor):

IActivator foo = new |

You should get a neat list of all of the classes in your current scope that implement IActivotor.

不要将您的类标记为static

The error message itself is clear, the S1 class cannot be static since you are creating an instance of it. Remove the static keyword from S1. Also, the access modifier and abstract modifier are invalid in an interface declaration.

In C#, interfaces cannot declare inner types.

My suggestion here is to use the Factory pattern to get the correct instances instead of nesting types in your interface (this increases coupling/dependencies).

interface IActivation
{
    double func(double inputput);
}

public static class ActivationFactory
{
    IActivation GetImplA()
    {
        return new ImplA();
    }

    IActivation GetImplB()
    {
        return new ImplB();
    }
}

class ImplA : IActivation { }
class ImplB : IActivation { }

If IActivation does not have to be an interface, you can turn it into an abstract class

public abstract class IActivation
{
    public abstract double func(double inputput);

    public class S1 : IActivation
    {
        public override double func(double input)
        {
            if (input > 0) return 1.0;
            return 0.0;
        }
    }
}

This changes the actual meaning of the code, but allows you to say

var s1 = new IActivation.S1();

Update The main issue I can think of is if you have a class that extends something else and implements this interface it won't work (you can't inherit from two classes). You could then create an interface and an abstract class that implements the abstract class but that's getting a little silly.

Another option is

public interface IActivation {
    // ...
}

public class Activation {
    public class S1 : IActivation { 
        // ...
    }
}

The advantage is you keep IActivation as an interface, but you have another class littering your namespace.

In both cases, you haven't done a direct port from Java.

use sigleton pattern for each S'i' implementation and tear appart interface and implementation as described above by cdhowie

It seems you don't need factory - unless your S'i' instances have own state?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM