The Common Language Specification
COM allows
objects created in different languages to communicate with one another. On the other
hand, the CLR now integrates all languages and allows objects created in one language
to be treated as equal citizens by code written in a completely different
language.
This
integration is possible because of the CLR’s standard set of types,
self-describing type information (metadata), and common execution environment.
While this
language integration is a fantastic goal, the truth of the matter is that
programming languages are very different from one another. For example, some
languages don’t treat symbols with case-sensitivity or don’t offer unsigned
integers, operator overloading, or methods that support a variable number of
parameters.
If you intend
to create types that are easily accessible from other programming languages, you
need to use only features of your programming language that are guaranteed to
be available in all other languages. To help you with this, Microsoft has
defined a Common
Language Specification (CLS) that details for compiler vendors
the minimum set of features that their compilers must support if these
compilers are to target the CLR.
The CLR/CTS
supports a lot more features than the subset defined by the CLS, so if you don’t
care about interlanguage operability, you can develop very rich types limited
only by the language’s feature set. Specifically, the CTS defines rules that
externally visible types and methods must adhere to if they are to be
accessible from any CLR-compliant programming language. Note that the CLS rules
don’t apply to code that is accessible only within the defining assembly. Figure 1-6 summarizes the ideas expressed in this
paragraph.
As Figure 1-6 shows, the CLR/CTS offers a set of
features. Some languages expose a large subset of the CLR/CTS. A programmer
willing to write in IL assembly language, for example, is able to use all the features
the CLR/CTS offers. Most other languages, such as C#, Visual
Basic, and
Fortran, expose a subset of the CLR/CTS features to the programmer. The CLS defines
the minimum set of features that all languages must support.
If you’re
designing a type in one language and you expect that type to be used by another
language, you shouldn’t take advantage of any features that are outside the
CLS. Doing so would mean that your type’s members might not be accessible by
programmers writing code in other programming languages. In the following code,
a CLS-compliant type is being defined in C#. However, the type has a few
non-CLS-compliant constructs causing the C# compiler to complain about the
code.
[assembly:CLSCompliant(true)]
// Errors appear because the class is public
p u b l i c c lass App {
// Error: Return type of ÔApp.Abc()’ is not
CLS-c o m p l i a n t
public UInt32 Abc() { return 0; }
// Error: Identifier ÔApp.abc()’ differing
// only in case is not CLS-c o m p l i a n t
public void abc() { }
// No error: Method is private
private UInt32 ABC() { return 0; }
In this code,
the [assembly:CLSCompliant(true)] attribute is applied to the assembly. This attribute tells
the compiler to ensure that any publicly exposed type doesn’t have anyconstruct
that would prevent the type from being accessed from any other programminglanguage.
When this code is compiled, the C# compiler emits two errors. The first error
is reported because the method Abc returns an unsigned integer; Visual Basic
and some other languages can’t manipulate unsigned integer values. The second
error is because this type exposes two public methods that differ only by case:
Abc and abc.
Visual Basic and some
other
languages can’t call both these methods.
Interestingly,
if you were to delete public from in front of Ôclass App’ and recompile, both errors would go away.
The reason is that the App type
would default to internal and would therefore no longer be exposed outside the assembly. For
a complete list of CLS rules, refer to the "Cross-Language
Interoperability" section in the .NET Framework SDK documentation.
Let me distill
the CLS rules to something very simple. In the CLR, every member of a type is either
a field (data) or a method (behavior). This means that every programming
language must be able to access fields and call methods. Certain fields and
certain methods are used in special and common ways. To ease programming,
languages typically offer additional abstractions to make coding these common
programming patterns easier. For example, languages expose concept s such as
enums, arrays, properties, indexers, delegates, events, constructors,
destructors, operator overloads, conversion operators, and so on. When a
compiler comes
across any of these things in your source code, it must translate these constructs
into fields and methods so that the CLR and any other programming language can
access the construct.
Consider the
following type definition, which contains a constructor, a destructor, some overloaded
operators, a property, an indexer, and an event. Note that the code shown is there
just to make the code compile; it doesn’t show the correct way to implement a
type.
using System;
class Test {
// Constructor
public Test() {}
// Destructor
~Test() {}
// Operator overload
p u b l i c s t a tic Boolean operator ==
(Test t1, Test t2) {
return true;
}
public static Boolean operator != (Test t1,
Test t2) {
return false;
}
// An operator overload
public static Test operator + (Test t1, Test
t2) { return null; }
// A property
public String AProperty {
get { return null; }
set { }
}
// An indexer
public String this[Int32 x] {
get { return null; }
set { }
}
// An event
event EventHandler AnEvent;
}The Common Language Specification
COM allows
objects created in different languages to communicate with one another. On the other
hand, the CLR now integrates all languages and allows objects created in one language
to be treated as equal citizens by code written in a completely different
language.
This
integration is possible because of the CLR’s standard set of types,
self-describing type information (metadata), and common execution environment.
While this
language integration is a fantastic goal, the truth of the matter is that
programming languages are very different from one another. For example, some
languages don’t treat symbols with case-sensitivity or don’t offer unsigned
integers, operator overloading, or methods that support a variable number of
parameters.
If you intend
to create types that are easily accessible from other programming languages, you
need to use only features of your programming language that are guaranteed to
be available in all other languages. To help you with this, Microsoft has
defined a Common
Language Specification (CLS) that details for compiler vendors
the minimum set of features that their compilers must support if these
compilers are to target the CLR.
The CLR/CTS
supports a lot more features than the subset defined by the CLS, so if you don’t
care about interlanguage operability, you can develop very rich types limited
only by the language’s feature set. Specifically, the CTS defines rules that
externally visible types and methods must adhere to if they are to be
accessible from any CLR-compliant programming language. Note that the CLS rules
don’t apply to code that is accessible only within the defining assembly. Figure 1-6 summarizes the ideas expressed in this
paragraph.
As Figure 1-6 shows, the CLR/CTS offers a set of
features. Some languages expose a large subset of the CLR/CTS. A programmer
willing to write in IL assembly language, for example, is able to use all the features
the CLR/CTS offers. Most other languages, such as C#, Visual
Basic, and
Fortran, expose a subset of the CLR/CTS features to the programmer. The CLS defines
the minimum set of features that all languages must support.
If you’re
designing a type in one language and you expect that type to be used by another
language, you shouldn’t take advantage of any features that are outside the
CLS. Doing so would mean that your type’s members might not be accessible by
programmers writing code in other programming languages. In the following code,
a CLS-compliant type is being defined in C#. However, the type has a few
non-CLS-compliant constructs causing the C# compiler to complain about the
code.
[assembly:CLSCompliant(true)]
// Errors appear because the class is public
p u b l i c c lass App {
// Error: Return type of ÔApp.Abc()’ is not
CLS-c o m p l i a n t
public UInt32 Abc() { return 0; }
// Error: Identifier ÔApp.abc()’ differing
// only in case is not CLS-c o m p l i a n t
public void abc() { }
// No error: Method is private
private UInt32 ABC() { return 0; }
In this code,
the [assembly:CLSCompliant(true)] attribute is applied to the assembly. This attribute tells
the compiler to ensure that any publicly exposed type doesn’t have anyconstruct
that would prevent the type from being accessed from any other programminglanguage.
When this code is compiled, the C# compiler emits two errors. The first error
is reported because the method Abc returns an unsigned integer; Visual Basic
and some other languages can’t manipulate unsigned integer values. The second
error is because this type exposes two public methods that differ only by case:
Abc and abc.
Visual Basic and some
other
languages can’t call both these methods.
Interestingly,
if you were to delete public from in front of Ôclass App’ and recompile, both errors would go away.
The reason is that the App type
would default to internal and would therefore no longer be exposed outside the assembly. For
a complete list of CLS rules, refer to the "Cross-Language
Interoperability" section in the .NET Framework SDK documentation.
Let me distill
the CLS rules to something very simple. In the CLR, every member of a type is either
a field (data) or a method (behavior). This means that every programming
language must be able to access fields and call methods. Certain fields and
certain methods are used in special and common ways. To ease programming,
languages typically offer additional abstractions to make coding these common
programming patterns easier. For example, languages expose concept s such as
enums, arrays, properties, indexers, delegates, events, constructors,
destructors, operator overloads, conversion operators, and so on. When a
compiler comes
across any of these things in your source code, it must translate these constructs
into fields and methods so that the CLR and any other programming language can
access the construct.
Consider the
following type definition, which contains a constructor, a destructor, some overloaded
operators, a property, an indexer, and an event. Note that the code shown is there
just to make the code compile; it doesn’t show the correct way to implement a
type.
using System;
class Test {
// Constructor
public Test() {}
// Destructor
~Test() {}
// Operator overload
p u b l i c s t a tic Boolean operator ==
(Test t1, Test t2) {
return true;
}
public static Boolean operator != (Test t1,
Test t2) {
return false;
}
// An operator overload
public static Test operator + (Test t1, Test
t2) { return null; }
// A property
public String AProperty {
get { return null; }
set { }
}
// An indexer
public String this[Int32 x] {
get { return null; }
set { }
}
// An event
event EventHandler AnEvent;
}
When the
compiler compiles this code, the result is a type that has a number of fields
and methods defined in it. You can easily see this using the IL Disassembler
tool (ILDasm.exe) provided with the .NET Framework SDK to examine the resulting
managed module, which is shown in Figure 1-7.
0 nhận xét Blogger 0 Facebook
Post a Comment
Thank for you