Replies: 43 comments 26 replies
-
Sounds like something accomplished easily through attributes and analyzers without requiring any modifications to the language. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour I can't enforce usage of a certain analyzer if someone uses my library. How else could I enforce overriding of a virtual method? |
Beta Was this translation helpful? Give feedback.
-
You can't, just like you couldn't if they decide to use a different version of the C# compiler without this support, or another compiler, or IL. It's a facility that doesn't exist in the CLR. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour value tuples with named members (C#7 feature) also doesn't exists on CLR side and are emulated by C# compiler. |
Beta Was this translation helpful? Give feedback.
-
Indeed, but tuples aren't trying to enforce anything. You can treat them as their raw type with no consequences at all. The worst thing that an errant compiler could do is ignore the names. A better comparison would be non-nullable references. Similarly they would only exist as attribute-based metadata and require a compiler that understands and can enforce the rules. That would make it just as easily defeatable as this proposal. However, there is significantly more benefit for non-nullable reference types than there is for this proposal given the frequency in which the use case occurs. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour The ideal outcome in my mind is for older versions of the compiler to fail to be able to create a derived class at all. Aren't there modreqs for this sort of thing? |
Beta Was this translation helpful? Give feedback.
-
@HaloFour We always have some ways to cheat. It's OK when some thing is enforced to prevent unintentional bugs. If someone intentionally seek a way to overcome restriction - he would find this way, no matter how you try to prevent him. Developer at any time can invoke private method with reflection, after all. And it's OK if he have serious reasons to do so. And it's not an argument to abandon private members of classes, if anyone can cheat this restriction by using reflection. |
Beta Was this translation helpful? Give feedback.
-
What's at stake here must be enforced with the same rigor as any other type safety rule. Anything less than enforcing this at the CLR level is worthless. |
Beta Was this translation helpful? Give feedback.
-
IIRC Type safety is pretty well enforced by the CLR. It's not like you can cheat by trying to define a generic type that doesn't respect a generic parameter constraint; that results in a runtime exception. Sure, you can call private methods through reflection, but doing so In any case, in my opinion the frequency in which a feature like this would really be useful is quite low so I don't see it gaining a lot of traction, particularly if it would involve CLR modifications in order to properly support. And the specific grammar of the proposal, a |
Beta Was this translation helpful? Give feedback.
-
@HaloFour If you try hard enough, you can totally overcome CLR type safety. You can use |
Beta Was this translation helpful? Give feedback.
-
Maybe, but you couldn't produce a perfectly verifiable and trustable assembly which does any of that. At the point that you're executing unmanaged/unsafe code all bets are off. But that's not particularly relevant to this discussion. If the goal is to provide a way for developers to avoid unintentional bugs through warnings then an analyzer seems like the appropriate tool. Modifying the compiler (and potentially the CLR, if you want any kind of actual enforcement) seems like quite a stretch to support what are likely only a handful of actual use cases. |
Beta Was this translation helpful? Give feedback.
-
Do I understand it correctly that the base method is not |
Beta Was this translation helpful? Give feedback.
-
@svick In the cases I'm thinking of, the base type must be instantiable. That rules out abstract methods. |
Beta Was this translation helpful? Give feedback.
-
Regarding CLR vs. C# safety: I've already seen multiple safety proposals dismissed due to lack of "backing" by the CLR. If we want to evolve C#'s safety features, we need to break some ties, and make compromises. Some things that are going to be "unsafe" at the code-level, will be totally safe at the CLR level. This is not really new. e.g. Private members can be accessed in an "unsafe" manner at the CLR level, but not at the source level. |
Beta Was this translation helpful? Give feedback.
-
I'm pretty sure this is incorrect. I've had the CLR reject plenty of stuff I've tried to do at the CLR level. Can you give an example? Reflection is by definition outside the safety rules of both IL and C#, so that doesn't count. |
Beta Was this translation helpful? Give feedback.
-
@YaakovDavis There must be a fundamental difference between |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi NAudio's MidiEvent hierarchy. (To be fair, it could have been designed better, but this is where we are...) |
Beta Was this translation helpful? Give feedback.
-
Expression compilation in fact uses I don't think IL verification even checks member visibility. Visibility aspects are part of the CTS, which is logically a level above what the JIT operates on. |
Beta Was this translation helpful? Give feedback.
-
Not so niche. It greatly impact architecture design of libraries and frameworks. Especially if library classes are expected to be extended. It's a clear way to minimize ability to "shoot yourself in a foot" when logic is required to be unique for each derived class (abstract or not). |
Beta Was this translation helpful? Give feedback.
-
How many other examples can you enumerate besides trying to force "deep cloning"? I'd suggest the number of concrete use cases can be counted on one hand. That's not a great impact. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour So, you can count any scenario which depend on actual data layout of class hierarchy (especially when new data fields/properties are introduced in derived classes and should be taken into account in overrided method logic) or require strict type identity. |
Beta Was this translation helpful? Give feedback.
-
"You can use it anywhere" is not a use case. "Deep cloning" and some very narrow definition of equality, that's two use cases so far. Both are offered by contract in the BCL and those definitions can't be changed so it's not like you can improve either of them. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour Do you say, data manipulation with data classes hierarchies are uncommon in C# projects? Are you sure?
It's easy to improve. Just mark those methods as 'mustoverride' in specific base class of own data classes hierarchy. |
Beta Was this translation helpful? Give feedback.
-
You supply analyzers with your library and say: "Guys, you should really use those analyzers. Otherwise you may make some common mistakes." You did your job. If developers choose to ignore your warning, it's their own fault when they make those mistakes. The same as it's their fault for ignoring docs and best practices. There are definitely some use cases for this proposal. I could find few in some of my previous projects. Still the benefit is tiny next to mentioned non-nullable references that I can imagine using all over my code. |
Beta Was this translation helpful? Give feedback.
-
In theory I believe you could even include your custom analysers in the same package as the library, so that they get auto-installed by NuGet. Not sure that'd work for xplat, .NET Core, or consumers using paket etc., but it is an option. |
Beta Was this translation helpful? Give feedback.
-
note that class that implements or overrides abstractly must be itself abstract. if you say it shouldn't be abstract then its design problem. because method must have implementation and non abstract class must have defined behavior. example
|
Beta Was this translation helpful? Give feedback.
-
No, the base class must not be abstract in this case. For example, a Clone method. You want that to be a virtual method but you want any derived class to override it. |
Beta Was this translation helpful? Give feedback.
-
You can easily enforce this at runtime. Compare the type of While I can see having this at compile time might be nice, I agree that is better suited to an analyzer. |
Beta Was this translation helpful? Give feedback.
-
NuGet-installed analyzers work as well as the compiler itself. The approach may still be new, but it's stable and reliable. There are two ways to distribute analyzers with a library (to form a "code aware library"):
When using the metadata package, option 2 behaves like option 1. However, it is more flexible because it allows the analyzer to be upgraded separately from the library, and also allows the library to be used without the analyzer if desired.
This statement isn't exactly true. While the compiler doesn't specifically provide and document this as a feature, there are ways it can be done. However, it comes at non-trivial risk for the person using the analyzer and I can't see any reason it would ever be worth the risk. As a result it is rather actively discouraged when the topic comes up. |
Beta Was this translation helpful? Give feedback.
-
I agree this is needed. It's great in dart (although implemented as an attribute that the compiler knows about.) [MustOverride] and [MustCallSuper] in their case. I think they should be modifiers on the call however and enforced even if no analyzer exists. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Introduce optional
mustoverride
method modifier for virtual methods.Every derived class should override this virtual method if modifier is applied on method in parent class.
Reason: some virtual method's implementations must be unique for every class. For example, if class supports "deep cloning" (or some customized serialization logic), every derived class should introduce its own version of
DeepClone()
method. If derived class doesn't override base classDeepClone()
, it's an obvious bug.At low-level it can be implemented as
[MustOverride]
attribute. Compiler should throw at least warning if any derived class doesn't override method.Beta Was this translation helpful? Give feedback.
All reactions