CLS Compliance? Whaaa?

vb-179What does this mean?  Why do I see this within some of my applications?  How do I fix this or how do I stop the message from showing.  I will get a little technical in my explanation before I answer those questions.

CLS is a Common Language specification, a document that specifies how multiple programming languages need to work to create a common byte-code.  We have been using .NET for so long, gotten used to the fact that manage applications work, write components in VB and you can use them in C# or C++ or other language that uses the CLS.

So, you write an application in your favourite (managed) language and the compiler will convert that application into IL or MSIL as it is called.  This is the byte-code, it is a common language specification that is JITed (or Compiled Just In Time, JIT), like Java.   This code is then converted into platform specific code to execute the application.  The purpose of it, but the real reality of it has not been seen in too many places is, if there was a full .NET Framework for Linux and Mac these applications created on Windows could execute there.  The code is not platform specific, the MSIL is converted into the object code for execution on that platform.

So, where does this fit in with the CLS problem?  Simple, the code that is created by the compiler is CLS compliant.  Meaning you can use it in other languages that compile for the MSIL.  This means following some rules that might not be common to all languages.

IF and this is a BIG IF, IF you do not plan on writing ANY components outside of VB then, in the AssemblyInfo.vb  file you can removed the line of code;

<Assembly: CLSCompliant(True)> 

Or, set it to False.  This means the rules for this assembly are ignored and warnings about CLS compliance will not be seen.  This is an assembly level attribute, and care should be taken to turn it off.

Often in VB, when creating classes we use the following for property declaration;

Public Class MySuperClass
    Private _tempValue As Integer
    Public Property TempValue() As String
        Get
            Return _tempValue
        End Get
        Set(value As String)
            _tempValue = value
        End Set
    End Property

End Class

Simple class definition, the temp variable, prefixed with an _ (underscore) because VB is not case sensitive.  In case sensitive languages you can distinguish them as;

public class Class1
    {
        private int tempValue;
        public int TempValue 
        {   get { return tempValue; } 
            set
            {
                tempValue=  value;   
            }
        }
    }

Since tempValue is different to TempValue in case sensitive code.  Both of these are CLS compliant code, both can be accessed from other CLS languages if required.

But a change to either of these to show

protected int tempValue;

or

Protected _tempValue As Integer

and suddenly both classes are not CLS compliant cannot be called by each other.  C# does not allow prefixed underscores (_) for use with variables and VB is not case sensitive and therefore there is not difference between tempValue and TempValue.

There are the following rules you should follow when making code CLS Compliant, which are as follows.

NOTE:  A note on the rules MOST of these pertain to publically exposed interfaces.  These are the areas that other languages can access if they import your class for use in their code.  If it can’t be accessed outside your application then use any/all of these.  But if you break one of them on public interfaces then you code can’t be considered CLS compliant.

NOTE 2: The default behaviour of the compilers is not to check for CLS Compliance and will allow you to break any of these rules.  Also note.  Unless All Warnings as errors is selected, then the application will compile happily and everything will work, until you try and access it from another CLS compliant language.

  1. Unsigned types should not be included in publically exposed interfaces.  So, ULong, UInt and o on are not CLS Compliant, why?  Possibly due to there being platforms that might not support unsigned numbers in certain types.  I am unsure why really, but it is part of the rule set.
  2. Unsafe types like pointer are a big no, no with public interfaces.  Why VB doesn’t support pointers directly but there is a CLS compliant structure called IntPtr which is CLS Compliant.  So if you use *pointers in C++/C#  and need to use them in VB then you will need to convert them to IntPtr (UIntPtr is not CLS Compliant, see rule 1.)
    int myVar = 25;
    int foo;
    
    foo = *myVar
    If (foo == myVar)
    {
    	myVar = 100;
    }
    

    This code shows the problems and this becomes a problem in VB.  Foo is not assigned the value 25, it is assigned the memory address of myVar so when the check happens, they will not be equal.

  3. It should NOT be case sensitive.  Simply put, anything that could be accessed outside the language you are writing in, can’t differ by only case.
    Dim tempValue as Integer
    Dim TEMPValue as Integer
    

    These are the same variable in VB and would cause an error in the compiler, but;

    int tempValue;
    int TEMPValue;
    

    Both are different in C++ but this isn’t CLS compliant and there would be complaints with this in non-case senstive languages.  There is MANY an argument that can be had with developers over real languages v toy languages and case sensitivity.

  4. Operators cannot be overloaded.  If in your class you are overriding an Operator like = or >= then you can only create one method. 
  5. Overloaded methods can’t differ by simply out or ref.  These are C# keywords which mean the same thing.  In VB, ByRef is the one name.   So;
    public int TempOut(int name, out int myMember)
    {
    	myMember = name;
       if (name > 0)
       		return name;
       	return 0;
    }
    
    public int TempOut(int name, ref int myMember)
    {
       myMember = name;
    	return name;
    }
    

    Might look different they are the same.  The difference is this breaks the compiler and and error will be given to you.  It is a rule for CLS Compliance but it is also a rule in C# and VB (though VB has only the one keyword to mean the same thing)

  6. Publically exposed members starting with an underscore (_).  We have seen this one above.  _ is used mainly in VB to provide a differentiating mechanism between private and public properties.  But in VB, an understand is still valid on public members.  But using them means your code is not CLS compliant and will not work with other languages.
  7. This one is a funny one, but, ONLY members that are CLSCompliant can be abstract.  Mmm, I don’t really understand this, but strangely you can create, by default a class without any mention of CLSCompliant and the assembly not stipulated as CLSCompliant will quiet happily take abstract members, but specify an Assembly to be CLSComplaint and a class and then specify that a Member is not CLSCompliant then it complains. 

There are other rules, dealing with arrays, constructors, enumerations and other things but the main languages, by that I say (C#, C++ (managed) and VB) support these rules by default, in most cases, there are exceptions as always but you can check out the full specification here, if you want more information.  I am happy to expand these at anytime if more information is required.

Advertisements

Posted on January 14, 2014, in Article, Development and tagged , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: