Practical limitations with assemblies not marked as CLS compliant?
Asked Answered
S

2

5

As an OSS library author, I've always tried to make my stuff CLS compliant. But MS doesn't make this easy. They often put you in catch-22 situations, such as the following:

  • You cannot have a protected variable differing only in case from the public property.
  • You cannot have protected or public variables starting in an underscore or 'm_'.
  • If you want to make a class really extensible, you often need to have protected variables matching public properties. Your least ugly exit is to add a suffix to the variable, like "Var" or "Value". That's nasty and unacceptable to me. I like clean code.

I know of no .NET languages that don't support variables starting in an underscore, and I've used them in many places where the variable needs to be visible to subclasses.

I'm tired of the warnings, and I'm planning on turning off CLS compliance at the assembly level on my 30+ C# libraries.

Are there any actual problems with turning off CLS compliance on libraries? Any real problems with doing this?

Microsoft has issued unheedable guidance on software for decades, with less that 5% of it being worth the bytes it was encoded in. I can't find any evidence that this best practice has any real effect on anything.

But, to be careful, I'm checking.

And no, this is not a duplicate of the inverse of this question: Any reason not to mark a DLL as CLSCompliant?

I'm looking for actual results and effects here, not the advice of a MS intern.

For example, if IronPython, IronRuby, or F# are unable to read or write a variable starting with an underscore, that's an effect, although it would only cause a problem for users subclassing certain objects.

If a language or tool is completely unable to use an assembly unless it is marked CLS compliant, now that's a big deal.

Sherburne answered 21/3, 2012 at 8:6 Comment(5)
-1. None of the cases you give as example make any sense.Gerrilee
@TomTom: I agree, thus my answer below, but I still think that the question per se is valid. There are other valid cases, that prevent CLS compliance. One example from a current project of mine: The project's name is REM. The root namespace of all projects in the solution is Rem.. With REM being a reserved keyword in some languages, this prevents CLS compliance.Countermand
Yes. IO am just a hugh fan of making a case PROPERLY or getting laughed at. The OP had all the time ni the world to sit down and come up with ONE sensible case.Gerrilee
@Gerrilee It's a sensible, if uncommon, case. I didn't mention the more obvious limitations of CLS compliance, well, because they're obvious. This is my personal gripe. Assume I disagree with all Microsoft philosophy on software and software development, and go from there. I'm asking about effects, results - not theory or justifications for avoiding the problem. Sorry if I annoyed you with my shot at Microsoft White Papers.Sherburne
Regardless of the examples there is a question in there and also evidence that a search has been done to stop duplicate questions. I see no need for the -1. Instead of picking the question apart I invested that time in reading a few MSDN entries in search of the elusive benefit of CLS compliance.Schuss
S
5

From what I can tell, an actual or real problem with non-compliance is you lose the guarantee.

http://msdn.microsoft.com/en-us/library/bhc3fa7f.aspx

It's like overclocking your computer or driving your car with a third party mod on it, you lose "official" support from the people originally supplying you if anything goes wrong (even if it happens to work).

In the case of CLS compliance, you lose support from MS about the interoperability of your code against other languages (my own emphasis):

If you design a CLS–compliant class library, your library will have a guarantee of interoperability with a wide range of programming languages

As for all the catch-22s, I've no idea. Can't say I've ever cared about CLS compliance.

Schuss answered 21/3, 2012 at 10:41 Comment(1)
Thanks! Someone who focused on the actual question. You're awesome!Sherburne
C
4

About the problem you used as an example:

  • If the public property has a public setter and getter, the protected variable is not needed, because derived classes can set the value using the public property.
  • If the public property doesn't have a public setter, give it a protected setter. This removes the need for a protected variable, because derived classes can set the value using the protected setter of the public property.
  • Public variables should be avoided completely.

Conclusion: There is normally no need for protected or even public variables. It can all be modeled using properties.

Countermand answered 21/3, 2012 at 8:20 Comment(25)
@Daniel Normally, you're right. But there are sometimes cases where a subclass should have the ability to bypass the validation that occurs in the public setter. Another case is when invalidation occurs in the public setter, yet the subclass needs to be able to control or avoid that invalidation.Sherburne
Bottom line - when a library you started in 2007 has 50+ plugins and is integrated into 10,000+ systems, renaming protected variables just to make the compiler happy isn't a great option.Sherburne
@ComputerLinguist: I still would not use a protected field for this. I would use correctly named methods for this case, because they communicate the intent very clearly. In your case, someone reading the code of your derived class needs to know that the public setter of the property in the base class does something you want to avoid and that's why you are accessing the field directly. A method SetAgeWithoutValidation would make your intention obvious.Countermand
Whenever I expect someone to subclass something, I provide such methods and ensure that everything is clear. When I don't expect something to be subclassed, but also don't want to prevent it, I just leave the internal variables marked protected. In .NET, most people follow the MS school of 'only allow what the library developer has already thought of'. In my ideal universe, there wouldn't be private variables. Ever. I've been thwarted from fixing MS bugs in the .NET framework thousands of times by that.Sherburne
@ComputerLinguist: I know, this discussion doesn't help you answer your question, but I am curious: If there were no private fields, what would you use instead? I hope your answer is not "protected fields", because that would simply mean that none of your classes protects its invariants.Countermand
@ComputerLinguist YAGNI! Don’t make classes extensible by default – in fact, make them sealed by default! Only design those classes for extensibility that need to be extended. In general, prefer interfaces and try to avoid inheritance as much as possible. Prefer composition. Your dilemma suffers entirely from bad class design, not technical limitations.Lati
The underscore convention is prevalent in nearly every language community, although the rarest in .NET. When you use or modify members that start with an underscore, you know you're depending on implementation-specific behavior. However, since the benefit may be avoiding a complete re-implementation of the given base class, that's usually an acceptable maintenance tradeoff, since implementations change very infrequently. I find it hilarious that .NET people get so caught up in the abstraction evangelism, but the .NET framework itself doesn't even use interfaces properly.Sherburne
@ComputerLinguist: I don't really see what the underscore convention has to do with protected fields. I am using the underscore convention because I think it makes the code easier to read, but still I avoid protected and public fields like the plague.Countermand
@KonradRudolph I consider it hubris to assume that it's possible to know what another coder will need to change about your code. It's certainly sane to assume they'll try to do something stupid, but that's an insolvable problem.Sherburne
@DanielHilgarth 1) For true invariants, there is readonly and/or methods. 2) I avoid public fields, but after 10 years I haven't yet found a good reason, and I'm coming to the conclusion that java made the smart choice in not implementing properties.Sherburne
Besides, if you use interfaces properly and extensively, what does the implementation matter? Make it as extendable and malleable as possible, so users don't have to duplicate code. I'd really like to hear the rationale behind the sealed argument.Sherburne
@ComputerLinguist It’s got nothing to do with hubris, it’s cautious design. If you don’t know how your class is going to be extended, you can’t anticipate and design your class for meaningful extension. “It’s certainly sane to assume they’ll try to do something stupid” – exactly! Which is why you should make classes sealed, to guard them against their stupidity. In programming, being prohibitive is better than being permissive.Lati
@ComputerLinguist A comprehensive explanation is really not possible in the comments but modern OO design holds that inheritance should generally be avoided since its disadvantages (dependencies, strong coupling) overweigh its advantages, and the same effect can always be achieved by using composition plus interfaces.Lati
@KonradRudolph Well, see, the prohibitive > permissive attitude is IMO the .NET community's greatest flaw and weakness. It lends to slow innovation and continual frustration. No matter how careful you are, stupid things will happen. But the more compromises you make to prevent stupidity, the more smart people and smart things you block as well.Sherburne
@Computer No, it’s got nothing to do with slow innovation and frustration. You are not blocking innovation by making an API well-defined. Furthermore, this attitude is by no means restricted to .NET. It’s a general principle in modern software design.Lati
@KonradRudolph Composition rules, I agree. C# doesn't do composition well. Extension methods can't have state, which makes them only a mediocre form of composition. So in the .NET world, inheritance is usually the only way out, as horrible as that is. But Microsoft has never cared that much for good theory.Sherburne
@ComputerLinguist: What is the connection between composition and extension methods?Countermand
@KonradRudolph I've been doing C# since '01, and Ruby & Python since '08. Guess which is easier to make stuff happen in, and why?Sherburne
@ComputerLinguist Erm, I think I mean something different than you by composition. Extension methods aren’t related to composition. In answer to your Ruby/Python remark: the reason why those are easier is simply that they require less boilerplate code. I program a lot (!) in Python but I always keep my interfaces minimal even there.Lati
@DanielHilgarth I figured the next comment would be... ".NET has Extension Methods, it does so do composition!"... and was stating how weak the link was. Mixins would be the term I assume you meant by composition.Sherburne
@ComputerLinguist: (1) Konrad was talking about composition, not me. (2) I am pretty sure he meant composition and not mixins when he said "composition"...Countermand
My assumption that you meant mixins by composition was based on the context - we were talking about ways to extend existing code externally in ways not prepared for by the original author.Sherburne
My original question was about the effects of setting CLSCompliant(false) for downstream users, not about why CLS compliance and my coding style don't get along. As someone has answered that, I'm going to go to sleep - it's nearly 7am in my timezone.Sherburne
Please edit any relevant information into the question and/or answer, and take this discussion to a chat room. The comment section of an answer is really not the best place to hold long discussions, and is meant for to-the-point comments about the answer.Amylaceous
This entire answer amd comment chain could be deleted, it is in no way relevant to the question asked, and it's about a example provided.Sherburne

© 2022 - 2024 — McMap. All rights reserved.