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

C# #:";无法创建静态类的实例";,c#,java,.net,static,C#,Java,.net,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;

我正在将一些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;
        }
    }
}
其他地方(用法):

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

  • 声明一个接口,并在其中嵌套该接口的几个静态实现(代码包含IActivation的其他实现,如“S2”、“S3”等,此处省略)
  • 这方面的典型使用场景是将变量分配给该接口的一个特定实现。此外,通过实例化该变量的方式,很清楚这些特定实现属于何处——从某种意义上说,嵌套声明将进一步提高代码的可读性 (例如,
    new IActivation.S1();
    明确说明S1是IActivation的具体实现)

  • 有趣的是,C#不喜欢整个事物的定义方式:“无法创建静态类‘IActivation.S1”的实例。有人知道如何重构代码以使1。二,。是否将被保留?

    不要将类标记为
    static
    在Java中,
    static
    内部类对其封闭类型的成员没有隐式访问权。在C#中,所有嵌套类型都不能访问其父类型的成员;您不需要在C#中添加修改器来触发此行为

    在C#中,
    静态
    类是
    抽象密封的
    ,因此不能创建或派生它们——这与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;
        }
    }
    

    如果您的目标是以某种“可读”的方式提供默认实现(尽管我不认为
    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();
            }
        }
    }
    
    然而,我不同意这种说法,即这更具可读性或更有帮助。在特定类型的上下文中构造对象时,VisualStudio将显示该类型的所有子类型。因此,如果您这样做(
    |
    表示光标):


    您应该得到当前作用域中实现IActivMotor的所有类的整洁列表。

    错误消息本身很清楚,S1类不能是静态的,因为您正在创建它的实例。从S1中删除static关键字。此外,访问修饰符和抽象修饰符在接口声明中无效

    在C#中,接口不能声明内部类型

    我的建议是使用工厂模式来获得正确的实例,而不是在接口中嵌套类型(这会增加耦合/依赖性)


    对每个S'i'实现使用sigleton模式,撕毁装置接口和实现,如cdhowie所述


    似乎您不需要工厂-除非您的S'i'实例有自己的状态?

    如果
    IActivation
    不必是一个接口,您可以将其转换为一个抽象类

    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;
            }
        }
    }
    
    这改变了代码的实际含义,但允许您说

    var s1 = new IActivation.S1();
    
    更新我能想到的主要问题是,如果有一个类扩展了其他东西并实现了这个接口,那么它将无法工作(不能从两个类继承)。然后,您可以创建一个接口和一个实现抽象类的抽象类,但这有点愚蠢

    另一个选择是

    public interface IActivation {
        // ...
    }
    
    public class Activation {
        public class S1 : IActivation { 
            // ...
        }
    }
    
    优点是您将IActivation作为一个接口,但是您的命名空间中有另一个类


    在这两种情况下,您都没有使用Java直接端口。

    为什么需要将类声明为静态?@Morvader:
    static
    ,当应用于类时,在Java中的含义与在C#中的含义不同。添加了这一点,希望能够从了解Java的人那里得到答案……不幸的是,单凭这一点是不行的,您将得到一个“S1”:尝试时接口无法声明类型错误。我认为它归结起来就是Bas和cdhowie(见下文)所说的:“在C#中,接口不能声明内部类型。”我只回答“不能创建静态类的实例”。我建议操作读取编译器错误,fortiori C#编译器会生成详细的错误描述。好吧,我问了一个具体的问题,你没有回答。另外,您的“答案”会导致进一步的不可编译代码,因此我不明白这一点。没错,这是我考虑过的可能性之一,但它会打破“代码可读性”约束(第2点)。因为这样您就必须使用受保护的IActivation activation=new S1()。最初的意图(这是我的猜测,因为代码不是我写的)是让某种形式的intellisense为您提供替代方案,如果您觉得必须使用另一个实现的话。在您的情况下,每个人都必须猜测其他实现是什么……我看到您在我第一次评论之后更新了您的答案,非常感谢。也许我应该澄清一点:在最初的程序员设计中,
    IActivation activation=new IActivation.|
    将列出所有可用的IActivation实现,而不是其他(例如,IActivation2的实现)。为了达到同样的效果,您需要使用工厂模式,这相当于imho的写入开销。没有进攻意味着,但我目前认为约翰的解决方案是最合适的,尽管它的缺点(在项目中不存在)。好主意!当使用这种将接口转换为抽象类的方法时,是否有任何缺点/副作用?也就是说,与接口声明相比,有什么我做不到的吗?无论如何,从Java到C#的100%端口是不可能的(在我的例子中),所以我不关心这一点(例如,C#中的方法声明没有“抛出”等价物)。解决方案1中唯一的缺点是您松开了“Impleme”
    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;
            }
        }
    }
    
    var s1 = new IActivation.S1();
    
    public interface IActivation {
        // ...
    }
    
    public class Activation {
        public class S1 : IActivation { 
            // ...
        }
    }