4

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, e.g. "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 (e.g. 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?

3
  • Why do you need to declare the class as static? Commented Aug 22, 2011 at 11:25
  • @Morvader: static, when applied to classes, has a different meaning in Java than in C#. Commented Aug 22, 2011 at 11:32
  • Added java which hopefully will draw answers from people who know Java... Commented Aug 22, 2011 at 12:23

5 Answers 5

11

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.

Sign up to request clarification or add additional context in comments.

2 Comments

True, that's one of the possibilities that I had considered, but it would break the "code readability" constraint (point 2.). Because then you'd have to use protected IActivation activation = new S1(); . The original intent (this is my conjecture, as the code is not from me) is to have some form of intellisense provide you with alternatives should you feel to have to use another implementation. In your case everyone would have to guess what the other implementations would be...
I see that you've updated your answer after my first comment, much appreciated. Maybe I should clarify a little: In the original programmer's design IActivation activation = new IActivation.| would list all available implementations of IActivation, and none other (e.g. implementations of IActivation2). In order to achieve the very same effect you'd need to put a factory pattern into use, which is quite the writing overhead imho. No offense meant, but I currently consider John's solution to be the most suited one, despite its drawbacks (which don't exist in the project).
6

Do not mark your class as static.

3 Comments

That alone won't do, unfortunately, you'll get a 'S1': interfaces cannot declare types error when you try. I think what it boils down to is what Bas and cdhowie (see further down) stated: "In C#, interfaces cannot declare inner types."
I only answer "Cannot create an instance of the static class". I propose to OP read compiler errors, a fortiori C# compiler produces detailed error description.
Well, i asked a specific question which you didn't answer anyway. Plus, your "answer" leads to further uncompilable code, so i don't see the point.
2

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.

5 Comments

Nice idea! Are there any drawbacks / sideeffects when using this way of converting interfaces to abstract classes? I.e., is there anything I wont be able to accomplish when compared to the interface declaration?
A 100% port from Java to C# is not possible (in my case) anyway, so I'm not concerned about that (e.g. there's no "throws" equivalent on method declarations in C#). The only drawback in solution 1 is that you loose the "Implement interface" intellisense feature (multiple inheritance isssues are easily to verify via "Find all references" and don't exist in my case). I'm also curious about whether the "override" has any negative impact on performance (shouldn't have). The 2nd solution basically uses the same technique from 1 (which is: nested classes are OK with C#, not interface-class mixes).
For inheritance in C# you have to specify either override or new (msdn.microsoft.com/en-us/library/ms173153(v=vs.80).aspx). In this case, override is what you want.
I'm aware of that, it's not the syntax I was referring to but rather the "internal implementation" of the override. For example, C++ would modify the internal vtable method pointers in case of an override. I just wondered how that's solved in C#, that's all. Anyway, I think your solution is the most feasible one -> Accepted.
Sorry, I don't know enough about the internal implementation to answer that.
2

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

Comments

0

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?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.