繁体   English   中英

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

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

我正在将一些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;
        }
    }
}

SomewhereElse(用法):

protected IActivation activation = new IActivation.S1();

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

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

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

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

如果您的目标是以某种“可读”的方式提供默认实现(尽管我认为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();
        }
    }
}

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

IActivator foo = new |

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

不要将您的类标记为static

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

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

我的建议是使用Factory模式来获取正确的实例而不是接口中的嵌套类型(这会增加耦合/依赖关系)。

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

如果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完成直接端口。

使用sigleton模式为每个S'i'实现和撕裂appart接口和实现如上所述由cdhowie

看来你不需要工厂 - 除非你的S'i'实例有自己的状态?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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