No doubt if you dabbled around in .NET you've come across an attribute in the System namespace called CLSCompliantAttribute (CLSCompliant for short). If not, try running FxCop against your code once in a while - you'll see it real quick. The CLS in this context doesn't mean 'CLear Screen'. Instead it is short for Common Language Specification.
What is the Common Language Specification you ask? Well, in brief, the CLS helps ensure interoperability between languages by defining basic language features and rules; it is a subset of the Common Type System (CTS). Code that is CLS-compliant is guaranteed to be accessible from another CLS-supporting programming language. This level of support and interoperability is fantastic.
If, when writing code you conform to the CLS rules, you forget to add the CLSCompliantAttribute to your assembly, your assembly is NOT compliant. However, if you take the time and effort to add the attribute to your assembly you enter a world where you must now ensure compliance in all types, or at least explicitly identify those that aren't. The same holds true for a type. If you mark a type (i.e. class, struct, interfaces, etc) as CLS-compliant, you must mark all non-CLS-compliant members. Alternatively, you could fix up your code to be CLS-compliant; there is usually a CLS-compliant mechanism that provides the same capabilities. Types that derive from non-compliant types are inherently not compliant and should therefore also be marked as such.
All you need to do to apply the attribute to your assembly is the following:
using System;
[assembly: CLSCompliant(true)]
As a best practice, I highly encourage you to add this attribute. It will definitely facilitate reuse of your components, and causes the C# compiler to check for compliance in all types.
But what are some of the rules associated with CLS compliance? What constitutes a non-compliant entity? Let's check it out.
1. Naming conventions: protected or public identifiers must begin with a letter. For example, you can't begin an identifier with an underscore.
2. Uniqueness of names: in order for a type to be CLS-compliant, it cannot contain members that differ in name solely by case. For example, the following is invalid:
class MyClass {
protected int value;
public int Value;
}
Some languages (such as C# support this), but it's not CLS-compliant, so an alternative might be the following (ok, I know, it's a lame example):
class MyClass {
protected int val;
public int Value;
}
3. Data types: variables of the unsigned varieties (e.g. uint, ulong, etc) are not CLS-compliant. If you expose an unsigned integer from a protected or public member, your type will not be compliant. Instead, consider using the signed variety.
I don't pretend to be exhaustive with this short set of rules, but these are the ones with which I believe most developers will run into trouble. For a more comprehensive view, check this out.
Perhaps it's important to mention that these rules (for the most part) apply only to protected and public members; these are the members that other CLS-compliant langauges will be using to interact with the objects. You can do what you want in private fields, variables, methods, types, etc.