C#:"无法创建静态类的实例"

MrC*_*rCC 4 .net c# java static

我正在将一些Java代码转换为C#,偶然发现以下奇怪的事情:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

SomewhereElse(用法):

protected IActivation activation = new IActivation.S1();
Run Code Online (Sandbox Code Playgroud)

看一下原始代码,很清楚这是什么意思:

  1. 声明一个接口并在其中嵌套该接口的几个静态实现(该代码包含IActivation的其他实现,例如"S2","S3"等,这里省略了).
  2. 这种情况的典型使用场景是将变量分配给该接口的一个特定实现.此外,通过您需要实例化该变量的方式,非常清楚这些特定实现所属的位置 - 从某种角度来说,嵌套声明将进一步提高代码的可读性(例如new IActivation.S1();,清楚地表明S1是一个具体实施IActivation).

有趣的是,C#并不喜欢定义整个事物的方式:" 无法创建静态类'IActivation.S1的实例 ".有没有人知道如何重构该代码的方式,以便1.和2.将被保留?

cdh*_*wie 11

在Java中,static内部类没有对其封闭类型成员的隐式访问.在C#中,所有嵌套类型都没有对父类型成员的访问权限; 您无需在C#中添加修饰符来触发此行为.

在C#中,static类是abstract sealed,因此它们不能被创建或派生 - 这与Java中的含义不同.此外,接口不能包含自己的类型声明.

尝试这样的事情:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您的目标是以某种"可读"的方式提供默认实现(尽管我认为IActivator.S1()本质上更具可读性......)那么您可以创建一个静态工厂类:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我对这个更具可读性或更有帮助的说法提出质疑.当在特定类型的上下文中构造对象时,Visual Studio将显示该类型的所有子类型.所以如果你这样做(|代表光标):

IActivator foo = new |
Run Code Online (Sandbox Code Playgroud)

您应该获得当前作用域中实现IActivotor的所有类的简洁列表.


Kir*_*huk 6

不要将你的班级标记为static.

  • 好吧,我问了一个你没有回答的具体问题.另外,你的"答案"导致进一步无法编译的代码,所以我不明白这一点. (2认同)