C# #:";无法创建静态类的实例";
我正在将一些Java代码转换为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;
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;
}
}
}
其他地方(用法):
看看原始代码,很清楚这是什么意思:
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 {
// ...
}
}