What is the equivalent of Java's final in C#?
在C语言中,Java的EDCOX1 0的等价物是什么?
- 在类顶部的一条评论说:"如果你重写了这个类,你就被解雇了!"(当然是开玩笑:)
EDCOX1的0个关键字在Java中有几种用法。它与c_中的sealed和readonly关键字都对应,这取决于使用它的上下文。
班
要防止子类化(从定义的类继承):
爪哇
1
| public final class MyFinalClass {...} |
C.*
1
| public sealed class MyFinalClass {...} |
方法
防止覆盖virtual方法。
爪哇
1 2 3 4
| public class MyClass
{
public final void myFinalMethod() {...}
} |
C.*
1 2 3 4
| public class MyClass : MyBaseClass
{
public sealed override void MyFinalMethod() {...}
} |
正如约阿希姆·绍尔指出的,这两种语言之间的一个显著差异是Java默认地将所有非静态方法标记为EDCOX1(3),而C则标记为EDCOX1(1)。因此,如果您希望停止对基类中已显式标记为virtual的方法的进一步重写,只需在C中使用sealed关键字。
变量
只允许变量分配一次:
爪哇
1
| public final double pi = 3.14; // essentially a constant |
C.*
1
| public readonly double pi = 3.14; // essentially a constant |
作为补充说明,readonly关键字的效果不同于const关键字的效果,因为readonly表达式是在运行时而不是编译时计算的,因此允许任意表达式。
- 我要补充的是,Java中的所有非静态方法默认都是虚拟的。因此,在C++中,您可以简单地在初始定义中省略虚拟化,您需要使用"最终"来避免在Java中重写它的子类。
- 好的答案——在Java中还有一个"最终"的用法——在本地变量或方法参数上,防止重新分配它。没有与此直接等效的c。
- 可以在constructors中修改readonly成员变量:pastebin.com/azqzygia
- 还要注意:如果在Java中声明一个成员变量作为最终变量,编译器会抱怨,如果不是每个构造函数都在每个代码路径中分配一个值,而C语言只能用只读成员变量在该场景中发出警告。
- @在C示例中,noldorin:public class MyClass { public sealed override void MyFinalMethod() {...} }将不会编译,因为没有什么可以覆盖的,我使它工作的唯一方法是沿着以下行执行:interface IMyClass { void MyFinalMethod(); } public abstract class MyClassSealer : IMyClass { public abstract void MyFinalMethod(); } public class MyClass : MyClassSealer { public sealed override void MyFinalMethod() { } }(粘贴到一个IDE中)有更好的方法吗?
- @是的,我的例子是隐式的,您需要从另一个类中进行子类化。你真的不需要这个接口;这是多余的,但其他方面看起来是对的。
- -1"鉴于C标记为密封"…这是不正确的。c默认标记方法non-virtual。正如您指出的,sealed关键字只允许用于重写方法,其含义与non-virtual截然不同。如果方法实际上是默认的sealed,那么使用new关键字隐藏方法是没有意义的。
- @诺尔多林:"没人说过别的。"我认为问题是你没有完全提到它。在这个上下文中,这是一个重要的点,考虑到Java的EDCOX1(8)不允许(假设该字段不是在构造函数中最初定义的),这是EDCOX1与0的比较。当OP甚至不知道C等价物最初是什么时,你怎么会认为这是"常识"?
- 注意:在Java中,可以将方法内的变量标记为EDCOX1(8)。在C中没有等价物-不能将方法中的变量标记为C中的readonly。
这取决于上下文。
- 对于final类或方法,c等价物是sealed。
- 对于final字段,c等价物是readonly。
- 对于final局部变量或方法参数,没有直接的C等价物。
- 实际上,没有要求在声明最终变量时对其进行赋值。""final"表示在引用变量之前必须由某个代码路径分配变量,并且没有代码路径允许变量被多次分配。这适用于实例变量,实际上这意味着构造函数必须显式分配变量。
- +对于For a final local variable or method parameter, there's no direct C# equivalent来说是一个巨大的区别。
- 如果正在实例化,则可以使用局部变量的const。它不是等价的,因为final当然允许您单独声明和初始化(因此具有不同的值),但只是为了以防万一您不知道…
- const只能用于值类型。据我所知,没有办法为局部引用类型生成有效常量。
- @唯一的例外是弦乐。
这里每个人缺少的是Java对最终成员变量的明确分配的保证。
对于具有最终成员变量v的C类,通过C的每个构造函数的每个可能的执行路径都必须精确地分配v一次-未能分配v或分配v两次或两次以上将导致错误。
C的readonly关键字没有这样的保证-编译器非常乐意不分配readonly成员,或者允许您在构造函数中多次分配它们。
所以,final和readonly(至少在成员变量方面)绝对不是等价的——final要严格得多。
如前所述,对于方法和类,sealed相当于final。
至于其他的,这是复杂的。
- 在声明中定义的(静态)常量上,只要const是基元类型或不可变类,就可以将其视为等效的。
- 在一个一旦离开构造函数就不应该重新分配的字段上,可以使用readonly,但它不等于final,即使在构造函数中,也只需要一个分配。
- 我想,一个应该只分配一次的局部变量不能在C中创建。如果您想知道为什么会有人需要它:您可以先声明一个变量,然后再声明一些if-else,切换case等等。通过将其声明为final,可以强制它只分配一次,如果没有,则会发生编译器错误。这需要行为良好的代码,因此错误较少。
综上所述,c没有直接等价于final。虽然Java缺少一些很好的C语言特性,但对于我来说,大多数Java程序员都能看到C语言无法传递等效的内容。
Java类最终和方法最终->密封。JAVA成员变量最终->只读为运行时常数,const为编译时常数。
局部变量final和方法参数final没有等价项
http://en.csharp online.net/csharp_常见问题解答:_什么是 u csharp_和 u java_常量声明之间的差异
C常量使用const关键字声明编译时常量,或使用readonly关键字声明运行时常量。在C语言和Java语言中,常数的语义是相同的。
密封的
- 这只是答案的一部分,因为它取决于上下文,添加解释和/或示例将使需要帮助的人更容易理解。