100% found this document useful (1 vote)
688 views2,644 pages

Tutorial Document

Tutorials for vb.net with visual studio 2017
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
688 views2,644 pages

Tutorial Document

Tutorials for vb.net with visual studio 2017
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 2644

Table of Contents

Welcome
.NET Guide
Get Started with .NET
Tour of .NET
.NET Microservices: Architecture for Containerized .NET Applications
.NET Architectural Components
.NET Standard
Target Frameworks
.NET Glossary
Choosing between .NET Core and .NET Framework for server apps
What is "managed code"?
Automatic Memory Management
Common Language Runtime (CLR)
Language Independence
Language Independence and Language-Independent Components
Framework Libraries
Class Library Overview
Base Types
.NET Class libraries
Portability Analyzer
Handling and throwing exceptions
.NET Assembly File Format
Garbage Collection
Generic types
Delegates and lambdas
LINQ
Common Type System & Common Language Specification
Asynchronous programming
Asynchronous programming in depth
Asynchronous Programming Patterns
Native interoperability
Collections and Data Structures
Numerics in .NET
Dates, times, and time zones
Events
Managed Execution Process
Metadata and Self-Describing Components
Building Console Applications
Parallel Processing and Concurrency
Application Essentials
File and Stream I/O
Globalization and Localization
Attributes
Framework Design Guidelines
XML Documents and Data
Threading
Parallel Programming
Security
Serialization
Developing for Multiple Platforms
.NET Core Guide
Get started
Get started with C# and Visual Studio Code
Build a C# Hello World app with .NET Core in Visual Studio 2017
Build a Visual Basic Hello World app with .NET Core in Visual Studio 2017
Build a class library with C# and .NET Core in Visual Studio 2017
Build a class library with Visual Basic and .NET Core in Visual Studio 2017
What's new in .NET Core
Windows Prerequisites
macOS Prerequisites
Linux Prerequisites
Tutorials
Building a complete .NET Core solution on Windows, using Visual Studio 2017
Get Started with C# and Visual Studio Code
Getting started with .NET Core on macOS
Getting started with .NET Core on macOS using Visual Studio for Mac
Building a complete .NET Core solution on macOS using Visual Studio for Mac
Getting started with .NET Core using the CLI tools
Developing Libraries with Cross Platform Tools
Developing ASP.NET Core applications
How to Manage Package Dependency Versions for .NET Core 1.0
Hosting .NET Core from native code
Create a custom template for dotnet new
Packages, Metapackages and Frameworks
Changes in CLI overview
Dependency management
Additions to the csproj format
Migration
Migration to csproj format
Mapping between project.json and csproj
Migrating from DNX
Application Deployment
Deploy apps with CLI tools
Deploy apps with Visual Studio
Creating a NuGet Package with Cross Platform Tools
Runtime package store
Docker
Building Docker Images for .NET Core Applications
Visual Studio Tools for Docker
Unit Testing
Unit testing with dotnet test and xUnit
Unit testing with dotnet test and MSTest
Running selective unit tests
Versioning
.NET Core Support
Runtime IDentifier catalog
.NET Core SDK Overview
.NET Core CLI Tools
Telemetry
Extensibility Model
Continuous Integration
Custom templates
dotnet
dotnet build
dotnet clean
dotnet help
dotnet install-script
dotnet migrate
dotnet msbuild
dotnet new
dotnet nuget delete
dotnet nuget locals
dotnet nuget push
dotnet pack
dotnet publish
dotnet restore
dotnet run
dotnet sln
dotnet store
dotnet test
dotnet vstest
Project modification commands
global.json
Porting from .NET Framework
Organizing projects for .NET Core
Analyzing third-party dependencies
Porting libraries
Build .NET Core from source
.NET Core distribution packaging
VS 2015/project.json docs
.NET Framework Guide
What's New
Get Started
Installation guide
Migration Guide
.NET Framework on Docker Guide
Running Console Apps in Containers
Development Guide
Application Domains and Assemblies
Resources in Desktop Apps
Accessibility
Data and Modeling
Client Applications
Service-Oriented Applications with WCF
Windows Workflow Foundation
Windows Service Applications
64-bit Applications
Web Applications with ASP.NET
Network Programming in the .NET Framework
Configuring Apps
Compiling Apps with .NET Native
Windows Identity Foundation
Debugging, Tracing, and Profiling
Deployment
Performance
Dynamic Programming
Managed Extensibility Framework (MEF)
Add-ins and Extensibility
Interoperating with Unmanaged Code
Unmanaged API Reference
XAML Services
Tools
Additional Class Libraries and APIs
C# Guide
Get Started
Tutorials
Tour of C#
What's new in C#
What's new in C# 7.1
What's new in C# 7
What's new in C# 6
Relationships between language and framework
C# Concepts
C# Type system
Namespaces
Basic Types
Classes
Structs
Tuples
Deconstructing tuples and other types
Interfaces
Methods
Properties
Indexers
Discards
Generics
Iterators
Delegates & events
Language Integrated Query (LINQ)
Asynchronous programming
Pattern Matching
Expression Trees
Native interoperability
Documenting your code
Versioning
C# Programming Guide
Language Reference
Walkthroughs
F# Guide
Tour of F#
Get Started
Get Started with Visual Studio
Get Started with Visual Studio for Mac
Get Started with Visual Studio Code and Ionide
Get Started with with the .NET Core CLI
Tutorials
F# Interactive
Type Providers
Introduction to Functional Programming
Functions as First-Class Values
Asynchronous and Concurrent Programming
Visual F# Development Environment Features
Configuring Projects
Targeting Older Versions of .NET
Using F# on Azure
Get started with Azure Blob storage using F#
Get started with Azure File storage using F#
Get started with Azure Queue storage using F#
Get started with Azure Table storage using F#
Package Management for F# Azure Dependencies
F# Language Reference
Keyword Reference
Symbol and Operator Reference
Functions
Values
Literals
F# Types
Type Inference
Primitive Types
Unit Type
Strings
Tuples
F# Collection Types
Lists
Options
Results
Sequences
Arrays
Generics
Records
Discriminated Unions
Enumerations
Reference Cells
Type Abbreviations
Classes
Structures
Inheritance
Interfaces
Abstract Classes
Members
Type Extensions
Parameters and Arguments
Operator Overloading
Flexible Types
Delegates
Object Expressions
Copy and Update Record Expressions
Casting and Conversions
Access Control
Conditional Expressions: if...then...else
Match Expressions
Pattern Matching
Active Patterns
Loops: for...to Expression
Loops: for...in Expression
Loops: while...do Expression
Assertions
Exception Handling
Attributes
Resource Management: the use Keyword
Namespaces
Modules
Import Declarations: The open Keyword
Signatures
Units of Measure
XML Documentation
Lazy Computations
Computation Expressions
Asynchronous Workflows
Query Expressions
Code Quotations
Fixed keyword
Compiler Directives
Compiler Options
Source Line, File, and Path Identifiers
Caller Information
Verbose Syntax
Code Formatting Guidelines
Visual Basic Guide
Get Started
What's New for Visual Basic
Visual Basic Breaking Changes in Visual Studio
Additional Resources for Visual Basic Programmers
Developing Applications
Programming in Visual Basic
Development with My
Accessing Data
Creating and Using Components
Printing and Reporting
Windows Forms Application Basics
Power Packs Controls
DataRepeater Control
Line and Shape Controls
Customizing Projects and Extending My with Visual Basic
Programming Concepts
Assemblies and the Global Assembly Cache
Asynchronous Programming with Async and Await
Attributes
Expression Trees
Iterators
Language-Integrated Query (LINQ)
Object-Oriented Programming
Reflection
Serialization
Threading
Program Structure and Code Conventions
Structure of a Program
Main Procedure
References and the Imports Statement
Namespaces
Naming Conventions
Coding Conventions
Conditional Compilation
How to: Break and Combine Statements in Code
How to: Collapse and Hide Sections of Code
How to: Label Statements
Special Characters in Code
Comments in Code
Keywords as Element Names in Code
Me, My, MyBase, and MyClass
Limitations
Language Features
Arrays
Collection Initializers
Constants and Enumerations
Control Flow
Data Types
Declared Elements
Delegates
Early and Late Binding
Error Types
Events
Interfaces
LINQ
Objects and Classes
Operators and Expressions
Procedures
Statements
Strings
Variables
XML
COM Interop
Introduction to COM Interop
How to: Reference COM Objects
How to: Work with ActiveX Controls
Walkthrough: Calling Windows APIs
How to: Call Windows APIs
How to: Call a Windows Function that Takes Unsigned Types
Walkthrough: Creating COM Objects
Troubleshooting Interoperability
COM Interoperability in .NET Framework Applications
Walkthrough: Implementing Inheritance with COM Objects
Language Reference
Typographic and Code Conventions
Visual Basic Runtime Library Members
Keywords
Attributes
Constants and Enumerations
Data Type Summary
Directives
Functions
Modifiers
Modules
Nothing
Objects
Operators
Properties
Queries
Statements
XML Comment Tags
XML Axis Properties
XML Literals
Error Messages
Reference
Command-Line Compiler
.NET Framework Reference Information
Language Specification
Sample Applications
Walkthroughs
Samples and Tutorials
Welcome to .NET
8/16/2017 • 1 min to read • Edit Online

See Getting Started with .NET Core to learn how to create .NET Core apps.
Build many types of apps with .NET, such as cloud, IoT, and games using free cross-platform tools. Your apps can
run on Android, iOS, Linux, macOS, and Windows. Deploy apps to servers or desktops and publish to app stores for
deployment on mobile devices. .NET is accessible to students and hobbyists, and all are welcome to participate in a
lively international developer community and make direct contributions to many of the .NET technologies.

News
.NET Core 2.0 Released!
Announcing .NET Core 2.0
Announcing .NET Standard 2.0
Announcing ASP.NET Core 2.0
Announcing Entity Framework Core 2.0
New for Visual Basic: .NET Standard Class Libraries and the dotnet CLI!
Visual Studio 2017 Version 15.3 Released
Introducing .NET Standard
Visual Studio for Mac: now generally available
Announcing Visual Studio 2017 General Availability
What's new for .NET Core and Visual Studio 2017 (video)
Announcing the .NET Framework 4.7
New Features in C# 7.0
Announcing F# 4.1 and the Visual F# Tools for Visual Studio 2017
Open Source Xamarin, Ready for you!
The week in .NET
Build 2017 on Channel 9 - Video on Microsoft's latest technologies and news!

Documentation
This documentation covers the breadth of .NET across platforms and languages. You can get started with .NET and
its languages in any of the following sections:
.NET Guide
.NET Core Guide
.NET Framework Guide
C# Guide
F# Guide
Visual Basic Guide
Additionally, you can browse the .NET API reference.

Open source
ihis documentation is completely open source. You can contribute in any way you like, from creating issues to
writing documentation. Additionally, much of .NET itself is open source:
.NET Core Home
.NET Libraries
.NET Core Runtime
Roslyn (C# and Visual Basic) Compiler Platform and IDE Tools
F# Compiler and IDE Tools
You can join other people who are already active in the .NET community to find out what's new or ask for help.
.NET Guide
7/29/2017 • 1 min to read • Edit Online

The .NET Guide provides a large amount of information about .NET. Depending on your familiarity with .NET, you
may wish to explore different sections of this guide and other sections of the .NET documentation.

New to .NET
If you're new to .NET, check out the Get Started article.
If you prefer to have a guided tour through major features of .NET, check out the Tour of .NET.
You can also read about .NET Architectural Components to get an overview of the various "pieces" of .NET and how
they fit together.

New to .NET Core


If you're new to .NET Core, check out Get Started with .NET Core.

New to .NET Standard


If you're new to .NET Standard, check out .NET Standard.

Porting .NET Framework Code to .NET Core


If you're looking to port an application, service, or some component of a system to .NET Core, check out Porting to
.NET Core from .NET Framework.

Porting a NuGet package from .NET Framework to .NET Standard or


.NET Core
If you're looking to port a NuGet package to .NET Standard, check out Porting to .NET Core from .NET Framework.
Tooling for .NET Standard and .NET Core are shared, so the content will be relevant for porting to .NET Standard as
well as .NET Core.

Interested in Major .NET Concepts


If you're interested in some of the major concepts of .NET, check out:
.NET Architectural Components
.NET Standard
Native Interoperability
Garbage Collection
Base Types in .NET
Collections
Dates, times, and time zones
Asynchronous Programming
Additionally, check out each language guide to learn about the three major .NET languages:
C# Guide
F# Guide
Visual Basic Guide

API Reference
Check out the .NET API Reference to see the breadth of APIs avaialable.
Get Started
8/14/2017 • 1 min to read • Edit Online

There are a number of ways to get started with .NET. Because .NET is a massive platform, there are multiple articles
in this documentation which show how you can get started with .NET, each from a different perspective.

Get started using .NET languages


The C# Getting Started articles and C# Tutorials provide a number of ways to get started in a C#-centric
way.
The F# Getting Started tutorials provide three primary ways you can use F#: with Visual Studio, Visual
Studio Code, or command-line tools.
The Visual Basic Getting Started articles provide guides for using Visual Basic in Visual Studio.

Get started using .NET Core


Getting Started with .NET Core provides an overview of articles which show how to get started with .NET
Core on different operating systems and using different tools.
The .NET Core Tutorials detail a number of ways you can get started with .NET Core using your operating
system and tooling of choice.

Get started using Docker on .NET Framework


Docker on .NET Framework shows how you can use .NET Framework on Windows Docker containers.
Tour of .NET
8/5/2017 • 9 min to read • Edit Online

.NET is a general purpose development platform. It has several key features, such as support for multiple
programming languages, asynchronous and concurrent programming models, and native interoperability, which
enable a wide range of scenarios across multiple platforms.
This article offers a guided tour through some of the key features of the .NET. See the .NET Architectural
Components topic to learn about the architectural pieces of .NET and what they're used for.

How to run the code samples


To learn how to set up a development environment to run the code samples, see the Getting Started topic. Copy
and paste code samples from this page into your environment to execute them.

Programming languages
.NET supports multiple programming languages. The .NET implementations implement the Common Language
Infrastructure (CLI), which among other things specifies a language-independent runtime and language
interoperability. This means that you choose any .NET language to build apps and services on .NET.
Microsoft actively develops and supports three .NET languages: C#, F#, and Visual Basic (VB).
C# is simple, powerful, type-safe, and object-oriented, while retaining the expressiveness and elegance of C-
style languages. Anyone familiar with C and similar languages finds few problems in adapting to C#. Check
out the C# Guide to learn more about C#.
F# is a cross-platform, functional-first programming language that also supports traditional object-oriented
and imperative programming. Check out the F# Guide to learn more about F#.
Visual Basic is an easy language to learn that you use to build a variety of apps that run on .NET. Among the
.NET languages, the syntax of VB is the closest to ordinary human language, often making it easier for
people new to software development.

Automatic memory management


.NET uses garbage collection (GC) to provide automatic memory management for programs. The GC operates on a
lazy approach to memory management, preferring app throughput to the immediate collection of memory. To
learn more about the .NET GC, check out Fundamentals of garbage collection (GC).
The following two lines both allocate memory:

var title = ".NET Primer";


var list = new List<string>();

There's no analogous keyword to de-allocate memory, as de-allocation happens automatically when the garbage
collector reclaims the memory through its scheduled run.
The garbage collector is one of the services that help ensure memory safety. A program is memory safe if it
accesses only allocated memory. For instance, the runtime ensures that an app doesn't access unallocated memory
beyond the bounds of an array.
In the following example, the runtime throws an InvalidIndexException exception to enforce memory safety:

int[] numbers = new int[42];


int number = numbers[42]; // Will throw an exception (indexes are 0-based)

Working with unmanaged resources


Some objects reference unmanaged resources. Unmanaged resources are resources that aren't automatically
maintained by the .NET runtime. For example, a file handle is an unmanaged resource. A FileStream object is a
managed object, but it references a file handle, which is unmanaged. When you're done using the FileStream, you
need to release the file handle.
In .NET, objects that reference unmanaged resources implement the IDisposable interface. When you're done using
the object, you call the object's Dispose() method, which is responsible for releasing any unmanaged resources.
.NET languages provide a convenient using syntax for such objects, as shown in the following example:

using System.IO;

using (FileStream stream = GetFileStream(context))


{
// Operations on the stream
}

Once the using block completes, the .NET runtime automatically calls the stream object's Dispose() method,
which releases the file handle. The runtime also does this if an exception causes control to leave the block.
For more details, see the following topics:
For C#, see the using Statement (C# Reference) topic.
For F#, see Resource Management: The use Keyword.
For VB, see the Using Statement (Visual Basic) topic.

Type safety
An object is an instance of a specific type. The only operations allowed for a given object are those of its type. A
Dog type may have Jump and WagTail methods but not a SumTotal method. A program only calls the methods
belonging to a given type. All other calls result in either a compile-time error or a run-time exception (in case of
using dynamic features or object ).
.NET languages are object-oriented with hierarchies of base and derived classes. The .NET runtime only allows
object casts and calls that align with the object hierarchy. Remember that every type defined in any .NET language
derives from the base Object type.

Dog dog = AnimalShelter.AdoptDog(); // Returns a Dog type.


Pet pet = (Pet)dog; // Dog derives from Pet.
pet.ActCute();
Car car = (Car)dog; // Will throw - no relationship between Car and Dog.
object temp = (object)dog; // Legal - a Dog is an object.

Type safety is also used to help enforce encapsulation by guaranteeing the fidelity of the accessor keywords.
Accessor keywords are artifacts which control access to members of a given type by other code. These are usually
used for various kinds of data within a type that are used to manage its behavior.
private Dog _nextDogToBeAdopted = AnimalShelter.AdoptDog()

C#, VB, and F# support local type inference. Type inference means that the compiler deduces the type of the
expression on the left-hand side from the expression on the right-hand side. This doesn't mean that the type safety
is broken or avoided. The resulting type does have a strong type with everything that implies. From the previous
example, dog and cat are rewritten to introduce type inference, and the remainder of the example is unchanged:

var dog = AnimalShelter.AdoptDog();


var pet = (Pet)dog;
pet.ActCute();
Car car = (Car)dog; // will throw - no relationship between Car and Dog
object temp = (object)dog; // legal - a Dog is an object
car = (Car)temp; // will throw - the runtime isn't fooled
car.Accelerate() // the dog won't like this, nor will the program get this far

F# has even further type inference capabilities than the method-local type inference found in C# and VB. To learn
more, see Type Inference.

Delegates and lambdas


A delegate is represented by a method signature. Any method with that signature can be assigned to the delegate
and is executed when the delegate is invoked.
Delegates are like C++ function pointers except that they're type safe. They're a kind of disconnected method
within the CLR type system. Regular methods are attached to a class and are only directly callable through static or
instance calling conventions.
In .NET, delegates are commonly used in event handlers, in defining asynchronous operations, and in lambda
expressions, which are a cornerstone of LINQ. Learn more in the Delegates and lambdas topic.

Generics
Generics allow the programmer to introduce a type parameter when designing their classes that allows the client
code (the users of the type) to specify the exact type to use in place of the type parameter.
Generics were added to help programmers implement generic data structures. Before their arrival in order for a
type such as the List type to be generic, it would have to work with elements that were of type object . This had
various performance and semantic problems, along with possible subtle runtime errors. The most notorious of the
latter is when a data structure contains, for instance, both integers and strings, and an InvalidCastException is
thrown on working with the list's members.
The following sample shows a basic program running using an instance of List<T> types:
using System;
using System.Collections.Generic;

namespace GenericsSampleShort
{
public static void Main(string[] args)
{
// List<string> is the client way of specifying the actual type for the type parameter T
List<string> listOfStrings = new List<string> { "First", "Second", "Third" };

// listOfStrings can accept only strings, both on read and write.


listOfStrings.Add("Fourth");

// Below will throw a compile-time error, since the type parameter


// specifies this list as containing only strings.
listOfStrings.Add(1);
}
}

For more information, see the Generic types (Generics) overview topic.

Async programming
Async programming is a first-class concept within .NET with async support in the runtime, framework libraries, and
.NET language constructs. Internally, they're based on objects (such as Task ), which take advantage of the
operating system to perform I/O-bound jobs as efficiently as possible.
To learn more about async programming in .NET, start with the Async overview topic.

Language Integrated Query (LINQ)


LINQ is a powerful set of features for C# and VB that allow you to write simple, declarative code for operating on
data. The data can be in many forms (such as in-memory objects, a SQL database, or an XML document), but the
LINQ code you write typically doesn't differ by data source.
To learn more and see some samples, see the LINQ (Language Integrated Query) topic.

Native interoperability
Every operating system includes an application programming interface (API) that provides system services. .NET
provides several ways to call those APIs.
The main way to do native interoperability is via "platform invoke" or P/Invoke for short, which is supported across
Linux and Windows platforms. A Windows-only way of doing native interoperability is known as "COM interop,"
which is used to work with COM components in managed code. It's built on top of the P/Invoke infrastructure, but
it works in subtly different ways.
Most of Mono's (and thus Xamarin's) interoperability support for Java and Objective-C are built similarly, that is,
they use the same principles.
Read more about it native interoperability in the Native interoperability topic.

Unsafe code
Depending on language support, the CLR lets you access native memory and do pointer arithmetic via unsafe
code. These operations are needed for certain algorithms and system interoperability. Although powerful, use of
unsafe code is discouraged unless it's necessary to interop with system APIs or implement the most efficient
algorithm. Unsafe code may not execute the same way in different environments and also loses the benefits of a
garbage collector and type safety. It's recommended to confine and centralize unsafe code as much as possible and
test that code thoroughly.
The following example is a modified version of the ToString() method from the StringBuilder class. It illustrates
how using unsafe code can efficiently implement an algorithm by moving around chunks of memory directly:

public override String ToString()


{
if (Length == 0)
return String.Empty;

string ret = string.FastAllocateString(Length);


StringBuilder chunk = this;
unsafe
{
fixed (char* destinationPtr = ret)
{
do
{
if (chunk.m_ChunkLength > 0)
{
// Copy these into local variables so that they are stable even in the presence of ----s
(hackers might do this)
char[] sourceArray = chunk.m_ChunkChars;
int chunkOffset = chunk.m_ChunkOffset;
int chunkLength = chunk.m_ChunkLength;

// Check that we will not overrun our boundaries.


if ((uint)(chunkLength + chunkOffset) <= ret.Length && (uint)chunkLength <=
(uint)sourceArray.Length)
{
fixed (char* sourcePtr = sourceArray)
string.wstrcpy(destinationPtr + chunkOffset, sourcePtr, chunkLength);
}
else
{
throw new ArgumentOutOfRangeException("chunkLength",
Environment.GetResourceString("ArgumentOutOfRange_Index"));
}
}
chunk = chunk.m_ChunkPrevious;
} while (chunk != null);
}
}
return ret;
}

Next steps
If you're interested in a tour of C# features, check out Tour of C#.
If you're interested in a tour of F# features, see Tour of F#.
If you want to get started with writing code of your own, visit Getting Started.
To learn about important components of .NET, check out .NET Architectural Components.
7/29/2017 • 5 min to read • Edit Online

.NET Microservices. Architecture for Containerized .NET


Applications
DOWNLOAD available at: https://aka.ms/microservicesebook
PUBLISHED BY
Microsoft Developer Division, .NET and Visual Studio product teams
A division of Microsoft Corporation
One Microsoft Way
Redmond, Washington 98052-6399
Copyright © 2017 by Microsoft Corporation
All rights reserved. No part of the contents of this book may be reproduced or transmitted in any form or by any
means without the written permission of the publisher.
This book is provided “as-is” and expresses the author’s views and opinions. The views, opinions and information
expressed in this book, including URL and other Internet website references, may change without notice.
Some examples depicted herein are provided for illustration only and are fictitious. No real association or
connection is intended or should be inferred.
Microsoft and the trademarks listed at http://www.microsoft.com on the “Trademarks” webpage are trademarks of
the Microsoft group of companies.
Mac and macOS are trademarks of Apple Inc.
The Docker whale logo is a registered trademark of Docker, Inc. Used by permission.
All other marks and logos are property of their respective owners.
Co-Authors:

Cesar de la Torre, Sr. PM, .NET product team, Microsoft Corp.


Bill Wagner, Sr. Content Developer, C+E, Microsoft Corp.
Mike Rousos, Principal Software Engineer, DevDiv CAT team, Microsoft

Editors:

Mike Pope
Steve Hoag

Participants and reviewers:

Jeffrey Ritcher, Partner Software Eng, Azure team, Microsoft


Jimmy Bogard, Chief Architect at Headspring
Udi Dahan, Founder & CEO, Particular Software
Jimmy Nilsson, Co-founder and CEO of Factor10
Glenn Condron, Sr. Program Manager, ASP.NET team
Mark Fussell, Principal PM Lead, Azure Service Fabric team, Microsoft
Diego Vega, PM Lead, Entity Framework team, Microsoft
Barry Dorrans, Sr. Security Program Manager
Rowan Miller, Sr. Program Manager, Microsoft
Ankit Asthana, Principal PM Manager, .NET team, Microsoft
Scott Hunter, Partner Director PM, .NET team, Microsoft
Dylan Reisenberger, Architect and Dev Lead at Polly
Steve Smith, Software Craftsman & Trainer at ASPSmith Ltd.
Ian Cooper, Coding Architect at Brighter
Unai Zorrilla, Architect and Dev Lead at Plain Concepts
Eduard Tomas, Dev Lead at Plain Concepts
Ramon Tomas, Developer at Plain Concepts
David Sanz, Developer at Plain Concepts
Javier Valero, Chief Operating Officer at Grupo Solutio
Pierre Millet, Sr. Consultant, Microsoft
Michael Friis, Product Manager, Docker Inc
Charles Lowell, Software Engineer, VS CAT team, Microsoft

Introduction
Enterprises are increasingly realizing cost savings, solving deployment problems, and improving DevOps and
production operations by using containers. Microsoft has been releasing container innovations for Windows and
Linux by creating products like Azure Container Service and Azure Service Fabric, and by partnering with industry
leaders like Docker, Mesosphere, and Kubernetes. These products deliver container solutions that help companies
build and deploy applications at cloud speed and scale, whatever their choice of platform or tools.
Docker is becoming the de facto standard in the container industry, supported by the most significant vendors in
the Windows and Linux ecosystems. (Microsoft is one of the main cloud vendors supporting Docker.) In the future,
Docker will probably be ubiquitous in any datacenter in the cloud or on-premises.
In addition, the microservices architecture is emerging as an important approach for distributed mission-critical
applications. In a microservice-based architecture, the application is built on a collection of services that can be
developed, tested, deployed, and versioned independently.

About this guide


This guide is an introduction to developing microservices-based applications and managing them using containers.
It discusses architectural design and implementation approaches using .NET Core and Docker containers. To make
it easier to get started with containers and microservices, the guide focuses on a reference containerized and
microservice-based application that you can explore. The sample application is available at the eShopOnContainers
GitHub repo.
This guide provides foundational development and architectural guidance primarily at a development environment
level with a focus on two technologies: Docker and .NET Core. Our intention is that you read this guide when
thinking about your application design without focusing on the infrastructure (cloud or on-premises) of your
production environment. You will make decisions about your infrastructure later, when you create your
production-ready applications. Therefore, this guide is intended to be infrastructure agnostic and more
development-environment-centric.
After you have studied this guide, your next step would be to learn about production-ready microservices on
Microsoft Azure.

What this guide does not cover


This guide does not focus on the application lifecycle, DevOps, CI/CD pipelines, or team work. The complementary
guide Containerized Docker Application Lifecycle with Microsoft Platform and Tools focuses on that subject. The
current guide also does not provide implementation details on Azure infrastructure, such as information on specific
orchestrators.
Additional resources
Containerized Docker Application Lifecycle with Microsoft Platform and Tools (downloadable eBook)
https://aka.ms/dockerlifecycleebook

Who should use this guide


We wrote this guide for developers and solution architects who are new to Docker-based application development
and to microservices-based architecture. This guide is for you if you want to learn how to architect, design, and
implement proof-of-concept applications with Microsoft development technologies (with special focus on .NET
Core) and with Docker containers.
You will also find this guide useful if you are a technical decision maker, such as an enterprise architect, who wants
an architecture and technology overview before you decide on what approach to select for new and modern
distributed applications.
How to use this guide
The first part of this guide introduces Docker containers, discusses how to choose between .NET Core and the .NET
Framework as a development framework, and provides an overview of microservices. This content is for architects
and technical decision makers who want an overview but who do not need to focus on code implementation
details.
The second part of the guide starts with the Development process for Docker based applications section. It focuses
on development and microservice patterns for implementing applications using .NET Core and Docker. This section
will be of most interest to developers and architects who want to focus on code and on patterns and
implementation details.

Related microservice and container-based reference application:


eShopOnContainers
The eShopOnContainers application is a reference app for .NET Core and microservices that is designed to be
deployed using Docker containers. The application consists of multiple subsystems, including several e-store UI
front ends (a Web app and a native mobile app). It also includes the back-end microservices and containers for all
required server-side operations.
This microservice and container-based application source code is open source and available at the
eShopOnContainers GitHub repo.

Send us your feedback!


We wrote this guide to help you understand the architecture of containerized applications and microservices in
.NET. The guide and related reference application will be evolving, so we welcome your feedback! If you have
comments about how this guide can be improved, please send them to:
[email protected]

NEXT
.NET architectural components
8/24/2017 • 4 min to read • Edit Online

A .NET app is developed for and runs in one or more implementations of .NET. Implementations of .NET include
the .NET Framework, .NET Core, and Mono. There is an API specification common to all implementations of .NET
that's called the .NET Standard. This article gives a brief introduction to each of these concepts.

.NET Standard
The .NET Standard is a set of APIs that are implemented by the Base Class Library of a .NET implementation. More
formally, it's a specification of .NET APIs that make up a uniform set of contracts that you compile your code
against. These contracts are implemented in each .NET implementation. This enables portability across different
.NET implementations, effectively allowing your code to run everywhere.
The .NET Standard is also a target framework. If your code targets a version of the .NET Standard, it can run on any
.NET implementation which supports that version of the .NET Standard.
To learn more about the .NET Standard and how to target it, see the .NET Standard topic.

.NET implementations
Each implementation of .NET includes the following components:
One or more runtimes. Examples: CLR for .NET Framework, CoreCLR and CoreRT for .NET Core.
A class library that implements the .NET Standard and may implement additional APIs. Examples: .NET
Framework Base Class Library, .NET Core Base Class Library.
Optionally, one or more application frameworks. Examples: ASP.NET, Windows Forms, and Windows
Presentation Foundation (WPF) are included in the .NET Framework.
Optionally, development tools. Some development tools are shared among multiple implementations.
There are four primary .NET implementations that Microsoft actively develops and maintains: .NET Core, .NET
Framework, Mono, and UWP.
.NET Core
.NET Core is a cross-platform implementation of .NET and designed to handle server and cloud workloads at scale.
It runs on Windows, macOS and Linux. It implements the .NET Standard, so code that targets the .NET Standard
can run on .NET Core. ASP.NET Core runs on .NET Core.
To learn more about .NET Core, see the .NET Core Guide and Choosing between .NET Core and .NET Framework
for server apps.
.NET Framework
The.NET Framework is the original .NET implementation that has existed since 2002. It's the same .NET Framework
that existing .NET developers have always used. Versions 4.5 and later implement the .NET Standard, so code that
targets the .NET Standard can run on those versions of the .NET Framework. It contains additional Windows-
specific APIs, such as APIs for Windows desktop development with Windows Forms and WPF. The .NET
Framework is optimized for building Windows desktop applications.
To learn more about the .NET Framework, see the .NET Framework Guide.
Mono
Mono is a .NET implementation that is mainly used when a small runtime is required. It is the runtime that powers
Xamarin applications on Android, Mac, iOS, tvOS and watchOS and is focused primarily on a small footprint.
It supports all of the currently published .NET Standard versions.
Historically, Mono implemented the larger API of the .NET Framework and emulated some of the most popular
capabilities on Unix. It is sometimes used to run .NET applications that rely on those capabilities on Unix.
Mono is typically used with a just-in-time compiler, but it also features a full static compiler (ahead-of-time
compilation) that is used on platforms like iOS.
To learn more about Mono, see the Mono documentation.
Universal Windows Platform (UWP)
UWP is an implementation of .NET that is used for building modern, touch-enabled Windows applications and
software for the Internet of Things (IoT). It's designed to unify the different types of devices that you may want to
target, including PCs, tablets, phablets, phones, and even the Xbox. UWP provides many services, such as a
centralized app store, an execution environment (AppContainer), and a set of Windows APIs to use instead of
Win32 (WinRT). Apps can be written in C++, C#, VB.NET, and JavaScript. When using C# and VB.NET, the .NET APIs
are provided by .NET Core.
To learn more about UWP, see Intro to the Universal Windows Platform.

.NET runtimes
A runtime is the execution environment for a managed program. The OS is part of the runtime environment but is
not part of the .NET runtime. Here are some examples of .NET runtimes:
Common Language Runtime (CLR) for the .NET Framework
Core Common Language Runtime (CoreCLR) for .NET Core
.NET Native for Universal Windows Platform
The Mono runtime for Xamarin.iOS, Xamarin.Android, Xamarin.Mac, and the Mono desktop framework

.NET tooling and common infrastructure


You have access to an extensive set of tools and infrastructure components that work with every implementation
of .NET. These include, but are not limited to the following:
The .NET languages and their compilers
The .NET project system (based on .csproj, .vbproj, and .fsproj files)
MSBuild, the build engine used to build projects
NuGet, Microsoft's package manager for .NET
Open-source build orchestration tools, such as CAKE and FAKE

See also
Choosing between .NET Core and .NET Framework for server apps
.NET Standard
.NET Core Guide
.NET Framework Guide
C# Guide
F# Guide
VB.NET Guide
.NET Standard
8/15/2017 • 7 min to read • Edit Online

The .NET Standard is a formal specification of .NET APIs that are intended to be available on all .NET
implementations. The motivation behind the .NET Standard is establishing greater uniformity in the .NET
ecosystem. ECMA 335 continues to establish uniformity for .NET implementation behavior, but there is no
similar spec for the .NET Base Class Libraries (BCL) for .NET library implementations.
The .NET Standard enables the following key scenarios:
Defines uniform set of BCL APIs for all .NET implementations to implement, independent of workload.
Enables developers to produce portable libraries that are usable across .NET implementations, using this
same set of APIs.
Reduces or even eliminates conditional compilation of shared source due to .NET APIs, only for OS APIs.
The various .NET implementations target specific versions of .NET Standard. Each .NET implementation version
advertises the highest .NET Standard version it supports, a statement that means it also supports previous
versions. For example, the .NET Framework 4.6 implements .NET Standard 1.3, which means that it exposes all
APIs defined in .NET Standard versions 1.0 through 1.3. Similarly, the .NET Framework 4.6.1 implements .NET
Standard 1.4, while .NET Core 1.0 implements .NET Standard 1.6.

.NET implementation support


The following table lists all versions of .NET Standard and the platforms supported:

.NET
STANDAR
D 1.0 1.1 1.2 1.3 1.4 1.5 1.6 2.0

.NET Core 1.0 1.0 1.0 1.0 1.0 1.0 1.0 2.0

.NET 4.5 4.5 4.5.1 4.6 4.6.1 4.6.2


Framewo
rk (with
.NET Core
1.x SDK)

.NET 4.5 4.5 4.5.1 4.6 4.6.1 4.6.1 4.6.1 4.6.1


Framewo
rk (with
.NET Core
2.0 SDK)

Mono 4.6 4.6 4.6 4.6 4.6 4.6 4.6 5.4

Xamarin.i 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.14


OS

Xamarin. 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.8


Mac
.NET
STANDAR
D 1.0 1.1 1.2 1.3 1.4 1.5 1.6 2.0

Xamarin. 7.0 7.0 7.0 7.0 7.0 7.0 7.0 7.5


Android

Universal 10.0 10.0 10.0 10.0 10.0 vNext vNext vNext


Windows
Platform

Windows 8.0 8.0 8.1

Windows 8.1 8.1 8.1


Phone

Windows 8.0
Phone
Silverlight

The columns represent .NET Standard versions. Each header cell is a link to a document that shows which
APIs got added in that version of .NET Standard.
The rows represent the different .NET implementations.
The version number in each cell indicates the minimum version of the implementation you'll need in order to
target that .NET Standard version.
To find the highest version of .NET Standard that you can target, do the following:
1. Find the row that indicate the .NET implementation you want to run on.
2. Find the column in that row that indicates your version starting from right to left.
3. The column header indicates the .NET Standard version that your target supports (and any lower .NET
Standard versions will also support it).
4. Repeat this process for each platform you want to target. If you have more than one target platform, you
should pick the smaller version among them. For example, if you want to run on .NET Framework 4.5 and
.NET Core 1.0, the highest .NET Standard version you can use is .NET Standard 1.1.
Which .NET Standard version to target
When choosing a .NET Standard version, you should consider this trade-off:
The higher the version, the more APIs are available to you.
The lower the version, the more platforms implement it.
In general, we recommend you to target the lowest version of .NET Standard possible. So, after you find the
highest .NET Standard version you can target, follow these steps:
1. Target the next lower version of .NET Standard and build your project.
2. If your project builds successfully, repeat step 1. Otherwise, retarget to the next higher version and that's the
version you should use.
.NET Standard versioning rules
There are two primary versioning rules:
Additive: .NET Standard versions are logically concentric circles: higher versions incorporate all APIs from
previous versions. There are no breaking changes between versions.
Immutable. Once shipped, .NET Standard versions are frozen. New APIs will first become available in specific
.NET implementations, such as .NET Core. If the .NET Standard review board believes the new APIs should be
made available everywhere, they'll be added in a new .NET Standard version.

Comparison to Portable Class Libraries


.NET Standard is the replacement for Portable Class Libraries (PCL). The .NET Standard improves on the
experience of creating portable libraries by curating a standard BCL and establishing greater uniformity across
.NET implementations as a result. A library that targets .NET Standard is a PCL or a ".NET Standard-based PCL".
Existing PCLs are "profile-based PCLs".
.NET Standard and PCL profiles were created for similar purposes but also differ in key ways.
Similarities:
Defines APIs that can be used for binary code sharing.
Differences:
.NET Standard is a curated set of APIs, while PCL profiles are defined by intersections of existing platforms.
.NET Standard linearly versions, while PCL profiles do not.
PCL profiles represents Microsoft platforms while the .NET Standard is agnostic to platform.

Specification
The .NET Standard specification is a standardized set of APIs. The specification is maintained by .NET
implementors, specifically Microsoft (includes .NET Framework, .NET Core and Mono) and Unity. A public
feedback process is used as part of establishing new .NET Standard versions through GitHub.
Official artifacts
The official specification is a set of .cs files that define the APIs that are part of the standard. The ref directory in
the dotnet/standard repository defines the .NET Standard APIs.
The NETStandard.Library metapackage (source) describes the set of libraries that define (in part) one or more
.NET Standard versions.
A given component, like System.Runtime, describes:
Part of .NET Standard (just its scope).
Multiple versions of .NET Standard, for that scope.
Derivative artifacts are provided to enable more convenient reading and to enable certain developer scenarios
(for example, using a compiler).
API list in markdown
Reference assemblies, distributed as NuGet packages and referenced by the NETStandard.Library
metapackage.
Package representation
The primary distribution vehicle for the .NET Standard reference assemblies is NuGet packages.
Implementations will be delivered in a variety of ways, appropriate for each .NET implementation.
NuGet packages target one or more frameworks. The .NET Standard packages target the ".NET Standard"
framework. You can target the .NET Standard Framework using the netstandard compact TFM (for example,
netstandard1.4 ). Libraries that are intended to run on multiple runtimes should target this framework.

The NETStandard.Library metapackage references the complete set of NuGet packages that define .NET
Standard. The most common way to target netstandard is by referencing this metapackage. It describes and
provides access to the ~40 .NET libraries and associated APIs that define .NET Standard. You can reference
additional packages that target netstandard to get access to additional APIs.
Versioning
The specification is not singular, but an incrementally growing and linearly versioned set of APIs. The first
version of the standard establishes a baseline set of APIs. Subsequent versions add APIs and inherit APIs defined
by previous versions. There is no established provision for removing APIs from the standard.
.NET Standard is not specific to any one .NET implementation, nor does it match the versioning scheme of any of
those runtimes.
APIs added to any of the implementations (such as, .NET Framework, .NET Core and Mono) can be considered as
candidates to add to the specification, particularly if they are thought to be fundamental in nature. New versions
of .NET Standard are created based on .NET implementation releases, enabling you to target new APIs from a
.NET Standard PCL. The versioning mechanics are described in more detail in .NET Core Versioning.
.NET Standard versioning is important for usage. Given a .NET Standard version, you can use libraries that target
that same or lower version. The following approach describes the workflow for using .NET Standard PCLs,
specific to .NET Standard targeting.
Select a .NET Standard version to use for your PCL.
Use libraries that depend on the same .NET Standard version or lower.
If you find a library that depends on a higher .NET Standard version, you either need to adopt that same
version or decide not to use that library.
PCL compatibility
.NET Standard is compatible with a subset of PCL profiles. .NET Standard 1.0, 1.1 and 1.2 each overlap with a set
of PCL profiles. This overlap was created for two reasons:
Enable .NET Standard-based PCLs to reference profile-based PCLs.
Enable profile-based PCLs to be packaged as .NET Standard-based PCLs.
Profile-based PCL compatibility is provided by the Microsoft.NETCore.Portable.Compatibility NuGet package.
This dependency is required when referencing NuGet packages that contain profile-based PCLs.
Profile-based PCLs packaged as netstandard are easier to consume than typically packaged profile-based PCLs.
netstandard packaging is compatible with existing users.

You can see the set of PCL profiles that are compatible with the .NET Standard:

PCL PROFILE .NET STANDARD PCL PLATFORMS

Profile7 1.1 .NET Framework 4.5, Windows 8

Profile31 1.0 Windows 8.1, Windows Phone


Silverlight 8.1

Profile32 1.2 Windows 8.1, Windows Phone 8.1

Profile44 1.2 .NET Framework 4.5.1, Windows 8.1

Profile49 1.0 .NET Framework 4.5, Windows Phone


Silverlight 8

Profile78 1.0 .NET Framework 4.5, Windows 8,


Windows Phone Silverlight 8
PCL PROFILE .NET STANDARD PCL PLATFORMS

Profile84 1.0 Windows Phone 8.1, Windows Phone


Silverlight 8.1

Profile111 1.1 .NET Framework 4.5, Windows 8,


Windows Phone 8.1

Profile151 1.2 .NET Framework 4.5.1, Windows 8.1,


Windows Phone 8.1

Profile157 1.0 Windows 8.1, Windows Phone 8.1,


Windows Phone Silverlight 8.1

Profile259 1.0 .NET Framework 4.5, Windows 8,


Windows Phone 8.1, Windows Phone
Silverlight 8

Targeting .NET Standard


You can build .NET Standard Libraries using a combination of the netstandard framework and the
NETStandard.Library metapackage. You can see examples of targeting the .NET Standard with .NET Core tools.

See also
.NET Standard Versions
Target frameworks
8/26/2017 • 4 min to read • Edit Online

When you target a framework in an app or library, you're specifying the set of APIs that you'd like to make
available to the app or library. You specify the target framework in your project file using Target Framework
Monikers (TFMs).
An app or library can target a version of .NET Standard. .NET Standard versions represent standardized sets of
APIs across all .NET implementations. For example, a library can target .NET Standard 1.6 and gain access to
APIs that function across .NET Core and .NET Framework using the same codebase.
An app or library can also target a specific .NET implementation to gain access to implementation-specific APIs.
For example, an app that targets Xamarin.iOS (for example, Xamarin.iOS10 ) gets access to Xamarin-provided
iOS API wrappers for iOS 10, or an app that targets the Universal Windows Platform (UWP, uap10.0 ) has
access to APIs that compile for devices that run Windows 10.
For some target frameworks (for example, the .NET Framework), the APIs are defined by the assemblies that the
framework installs on a system and may include application framework APIs (for example, ASP.NET).
For package-based target frameworks (for example, .NET Standard and .NET Core), the APIs are defined by the
packages included in the app or library. A metapackage is a NuGet package that has no content of its own but
is a list of dependencies (other packages). A NuGet package-based target framework implicitly specifies a
metapackage that references all the packages that together make up the framework.

Latest target framework versions


The following table defines the most common target frameworks, how they're referenced, and which version of
the .NET Standard they implement. These target framework versions are the latest stable versions. Pre-release
versions aren't shown. A Target Framework Moniker (TFM) is a standardized token format for specifying the
target framework of a .NET app or library.

TARGET FRAMEWORK .NET STANDARD


TARGET FRAMEWORK LATEST VERSION MONIKER (TFM) VERSION METAPACKAGE

.NET Standard 2.0.0 netstandard2.0 N/A NETStandard.Library

.NET Core 2.0.0 netcoreapp2.0 2.0 Microsoft.NETCore.A


Application pp

.NET Framework 4.7 net47 1.5 N/A

Supported target framework versions


A target framework is typically referenced by a TFM. The following table shows the target frameworks
supported by the .NET Core SDK and the NuGet client. Equivalents are shown within brackets. For example,
win81 is an equivalent TFM to netcore451 .

TARGET FRAMEWORK TFM


TARGET FRAMEWORK TFM

.NET Standard netstandard1.0


netstandard1.1
netstandard1.2
netstandard1.3
netstandard1.4
netstandard1.5
netstandard1.6
netstandard2.0

.NET Core netcoreapp1.0


netcoreapp1.1
netcoreapp2.0

.NET Framework net11


net20
net35
net40
net403
net45
net451
net452
net46
net461
net462
net47

Windows Store netcore [netcore45]


netcore45 [win] [win8]
netcore451 [win81]

.NET Micro Framework netmf

Silverlight sl4
sl5

Windows Phone wp [wp7]


wp7
wp75
wp8
wp81
wpa81

Universal Windows Platform uap [uap10.0]


uap10.0 [win10] [netcore50]

How to specify target frameworks


Target frameworks are specified in your project file. When a single target framework is specified, use the
TargetFramework element. The following console app project file demonstrates how to target .NET Core 2.0:
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>

</Project>

When you specify multiple target frameworks, you may conditionally reference assemblies for each target
framework. In your code, you can conditionally compile against those assemblies by using preprocessor
symbols with if-then-else logic.
The following library project file targets APIs of .NET Standard ( netstandard1.4 ) and APIs of the .NET
Framework ( net40 and net45 ). Use the plural TargetFrameworks element with multiple target frameworks.
Note how the Condition attributes include implementation-specific packages when the library is compiled for
the two .NET Framework TFMs:

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard1.4;net40;net45</TargetFrameworks>
</PropertyGroup>

<!-- Conditionally obtain references for the .NET Framework 4.0 target -->
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
<Reference Include="System.Net" />
</ItemGroup>

<!-- Conditionally obtain references for the .NET Framework 4.5 target -->
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<Reference Include="System.Net.Http" />
<Reference Include="System.Threading.Tasks" />
</ItemGroup>

</Project>

Within your library or app, you write conditional code to compile for each target framework:

public class MyClass


{
static void Main()
{
#if NET40
Console.WriteLine("Target framework: .NET Framework 4.0");
#elif NET45
Console.WriteLine("Target framework: .NET Framework 4.5");
#else
Console.WriteLine("Target framework: .NET Standard 1.4");
#endif
}
}

The build system is aware of preprocessor symbols representing the target frameworks shown in the
Supported target framework versions table. When using a symbol that represents a .NET Standard or .NET Core
TFM, replace the dot with an underscore and change lowercase letters to uppercase (for example, the symbol
for netstandard1.4 is NETSTANDARD1_4 ).
The complete list of preprocessor symbols for .NET Core target frameworks is:
TARGET FRAMEWORKS SYMBOLS

.NET Framework NET20 , NET35 , NET40 , NET45 , NET451 , NET452 ,


NET46 , NET461 , NET462 , NET47 , NET471

.NET Standard NETSTANDARD1_0 , NETSTANDARD1_1 , NETSTANDARD1_2 ,


NETSTANDARD1_3 , NETSTANDARD1_4 , NETSTANDARD1_5 ,
NETSTANDARD1_6 , NETSTANDARD2_0

.NET Core NETCOREAPP1_0 , NETCOREAPP1_1 , NETCOREAPP2_0

Deprecated target frameworks


The following target frameworks are deprecated. Packages targeting these target frameworks should migrate to
the indicated replacements.

DEPRECATED TFM REPLACEMENT

aspnet50 netcoreapp
aspnetcore50
dnxcore50
dnx
dnx45
dnx451
dnx452

dotnet netstandard
dotnet50
dotnet51
dotnet52
dotnet53
dotnet54
dotnet55
dotnet56

netcore50 uap10.0

win netcore45

win8 netcore45

win81 netcore451

win10 uap10.0

winrt netcore45

See also
Packages, Metapackages and Frameworks
Developing Libraries with Cross Platform Tools
.NET Standard
.NET Core Versioning
dotnet/standard GitHub repository
NuGet Tools GitHub Repository
Framework Profiles in .NET
.NET Glossary
8/14/2017 • 10 min to read • Edit Online

The primary goal of this glossary is to clarify meanings of selected terms and acronyms that appear frequently in
the .NET documentation without definitions.

AOT
Ahead-of-time compiler.
Similar to JIT, this compiler also translates IL to machine code. In contrast to JIT compilation, AOT compilation
happens before the application is executed and is usually performed on a different machine. Because AOT tool
chains don't compile at runtime, they don't have to minimize time spent compiling. That means they can spend
more time optimizing. Since the context of AOT is the entire application, the AOT compiler also performs cross-
module linking and whole-program analysis, which means that all references are followed and a single executable
is produced.

ASP.NET
The original ASP.NET implementation that ships with the .NET Framework.
Sometimes ASP.NET is an umbrella term that refers to both ASP.NET implementations including ASP.NET Core. The
meaning that the term carries in any given instance is determined by context.
See ASP.NET.

ASP.NET Core
A cross-platform, high-performance, open source implementation of ASP.NET built on .NET Core.
See ASP.NET Core.

assembly
A .dll file that contains a collection of APIs that can be called by apps or other assemblies.
A .NET assembly is a collection of types. An assembly includes interfaces, classes, structures, enumerations, and
delegates. Assemblies in a project's bin folder are sometimes referred to as binaries. See also library.

CLR
Common Language Runtime.
The exact meaning depends on the context, but this usually refers to the runtime of the .NET Framework. The CLR
handles memory allocation and management. The CLR is also a virtual machine that not only executes apps but
also generates and compiles code on-the-fly using a JIT compiler. The current Microsoft CLR implementation is
Windows only.

CoreCLR
.NET Core Common Language Runtime.
This CLR is built from the same code base as the CLR. Originally, CoreCLR was the runtime of Silverlight and was
designed to run on multiple platforms, specifically Windows and OS X. CoreCLR is now part of .NET Core and
represents a simplified version of the CLR. It's still a cross platform runtime, now including support for many Linux
distributions. CoreCLR is also a virtual machine with JIT and code execution capabilities.

CoreFX
.NET Core Base Class Library (BCL)
A set of libraries that comprise the System.* (and to a limited extent Microsoft.*) namespaces. The BCL is a general
purpose, lower-level framework that higher-level application frameworks, such as ASP.NET Core, build on. The
source code of the .NET Core BCL is contained in the CoreFX repository. However, the majority of the .NET Core
APIs are also available in the .NET Framework, so you can think of CoreFX as a fork of the .NET Framework BCL.

CoreRT
.NET Core runtime.
In contrast to the CLR/CoreCLR, CoreRT is not a virtual machine, which means it doesn't include the facilities to
generate and run code on-the-fly because it doesn't include a JIT. It does, however, include the GC and the ability
for runtime type identification (RTTI) and reflection. However, its type system is designed so that metadata for
reflection isn't required. This enables having an AOT tool chain that can link away superfluous metadata and (more
importantly) identify code that the app doesn't use. CoreRT is in development.
See Intro to .NET Native and CoreRT

ecosystem
All of the runtime software, development tools, and community resources that are used to build and run
applications for a given technology.
The term ".NET ecosystem" differs from similar terms such as ".NET stack" in its inclusion of third-party apps and
libraries. Here's an example in a sentence:
"The motivation behind the .NET Standard is to establish greater uniformity in the .NET ecosystem."

framework
In general, a comprehensive collection of APIs that facilitates development and deployment of applications that are
based on a particular technology. In this general sense, ASP.NET Core and Windows Forms are examples of
application frameworks. See also library.
The word "framework" has a more specific technical meaning in the following terms:
.NET Framework
target framework
TFM (target framework moniker)
In the existing documentation, "framework" sometimes refers to an implementation of .NET. For example, an article
may call .NET Core a framework. We plan to eliminate this confusing usage from the documentation.

GC
Garbage collector.
The garbage collector is an implementation of automatic memory management. The GC frees memory occupied by
objects that are no longer in use.
See Garbage Collection.

IL
Intermediate language.
Higher-level .NET languages, such as C#, compile down to a hardware-agnostic instruction set, which is called
Intermediate Language (IL). IL is sometimes referred to as MSIL (Microsoft IL) or CIL (Common IL).

JIT
Just-in-time compiler.
Similar to AOT, this compiler translates IL to machine code that the processor understands. Unlike AOT, JIT
compilation happens on demand and is performed on the same machine that the code needs to run on. Since JIT
compilation occurs during execution of the application, compile time is part of the run time. Thus, JIT compilers
have to balance time spent optimizing code against the savings that the resulting code can produce. But a JIT knows
the actual hardware and can free developers from having to ship different implementations.

implementation of .NET
An implementation of .NET includes the following:
One or more runtimes. Examples: CLR, CoreCLR, CoreRT.
A class library that implements a version of the .NET Standard and may include additional APIs. Examples: .NET
Framework Base Class Library, .NET Core Base Class Library.
Optionally, one or more application frameworks. Examples: ASP.NET, Windows Forms, and WPF are included in
the .NET Framework.
Optionally, development tools. Some development tools are shared among multiple implementations.
Examples of .NET implementations:
.NET Framework
.NET Core
Universal Windows Platform (UWP)

library
A collection of APIs that can be called by apps or other libraries. A .NET library is composed of one or more
assemblies.
The words library and framework are often used synonymously.

metapackage
A NuGet package that has no library of its own but is only a list of dependencies. The included packages can
optionally establish the API for a target framework.
See Packages, Metapackages and Frameworks

Mono
An open source alternative to the .NET Framework.
Mono started around the same time the .NET Framework was first released. Since the .NET Framework wasn't open
source, Mono was forced to start from scratch and is thus a complete re-implementation of the .NET Framework
with no shared code.
When .NET Core was released under the MIT license, Microsoft also released large chunks of the .NET Framework
under the MIT license as well. This enabled the Mono community to use the same code the .NET Framework uses in
order to close gaps and avoid behavioral differences.
Mono is primarily used to run .NET applications on Linux and macOS. There are ports of Mono to other platforms;
see Mono's Supported Platforms. Mono has implementations (though not necessarily complete) of WinForms,
ASP.NET, and System.Drawing .

.NET
The umbrella term for .NET Standard and all .NET implementations and workloads. Always capitalized, never ".Net".
See the .NET Guide

.NET Core
A cross-platform, high-performance, open source implementation of .NET. Includes the Core Common Language
Runtime (CoreCLR), the Core AOT Runtime (CoreRT, in development), the Core Base Class Library, and the Core
SDK.
See .NET Core.

.NET Core CLI


A cross-platform toolchain for developing .NET Core applications.
See .NET Core command-line interface (CLI) tools.

.NET Core SDK


A set of libraries and tools that allow developers to create .NET Core applications and libraries. Includes the .NET
Core CLI for building apps, .NET Core libraries and runtime for building and running apps, and the dotnet
executable (dotnet.exe) that runs CLI commands and runs applications.
See .NET Core SDK Overview.

.NET Framework
An implementation of .NET that runs only on Windows. Includes the Common Language Runtime (CLR), the Base
Class Library, and application framework libraries such as ASP.NET, Windows Forms, and WPF.
See .NET Framework Guide.

.NET Native
A compiler tool chain that produces native code ahead-of-time (AOT), as opposed to just-in-time (JIT).
Compilation happens on the developer's machine similar to the way a C++ compiler and linker works. It removes
unused code and spends more time optimizing it. It extracts code from libraries and merges them into the
executable. The result is a single module that represents the entire app.
UWP was the first application framework supported by .NET Native. Now, we support building native console apps
for Windows, macOS, and Linux.
See Intro to .NET Native and CoreRT
.NET Standard
A formal specification of .NET APIs that are available in each .NET implementation.
The .NET Standard specification is sometimes called a library in the documentation. Because a library includes API
implementations, not only specifications (interfaces), it's misleading to call .NET Standard a "library." We plan to
eliminate that usage from the documentation, except in reference to the name of the .NET Standard metapackage (
NETStandard.Library ).

See .NET Standard.

NGEN
Native (image) generation.
You can think of this technology as a persistent JIT compiler. It usually compiles code on the machine where the
code is executed, but compilation typically occurs at install time.

package
A NuGet package — or just a package — is a .zip file with one or more assemblies of the same name along with
additional metadata such as the author name.
The .zip file has a .nupkg extension and may contain assets, such as .dll files and .xml files, for use with multiple
frameworks and versions. When installed in an app or library, the appropriate assets are selected based on the
target framework specified by the app or library. The assets that define the interface are in the ref folder, and the
assets that define the implementation are in the lib folder.

platform
An operating system and the hardware it runs on, such as Windows, macOS, Linux, iOS, and Android.
Here are examples of usage in sentences:
".NET Core is a cross-platform implementation of .NET."
"PCL profiles represent Microsoft platforms, while the .NET Standard is agnostic to platform."
The .NET documentation frequently uses ".NET platform" to mean either an implementation of .NET or the .NET
stack including all implementations. Both of these usages tend to get confused with the primary (OS/hardware)
meaning, so we plan to eliminate these usages from the documentation.

runtime
The execution environment for a managed program.
The OS is part of the runtime environment but is not part of the .NET runtime. Here are some examples of .NET
runtimes:
Common Language Runtime (CLR)
Core Common Language Runtime (CoreCLR)
.NET Native (for UWP)
Mono runtime
The .NET documentation sometimes uses "runtime" to mean an implementation of .NET. For example, in the
following sentences "runtime" should be replaced with "implementation":
"The various .NET runtimes implement specific versions of .NET Standard."
"Libraries that are intended to run on multiple runtimes should target this framework." (referring to .NET
Standard)
"The various .NET runtimes implement specific versions of .NET Standard. … Each .NET runtime version
advertises the highest .NET Standard version it supports …"
We plan to eliminate this inconsistent usage.

stack
A set of programming technologies that are used together to build and run applications.
"The .NET stack" refers to the .NET Standard and all .NET implementations. The phrase "a .NET stack" may refer to
one implementation of .NET.

target framework
The collection of APIs that a .NET app or library relies on.
An app or library can target a version of .NET Standard (for example, .NET Standard 2.0), which is specification for a
standardized set of APIs across all .NET implementations. An app or library can also target a version of a specific
.NET implementation, in which case it gets access to implementation-specific APIs. For example, an app that targets
Xamarin.iOS gets access to Xamarin-provided iOS API wrappers.
For some target frameworks (for example, the .NET Framework) the available APIs are defined by the assemblies
that a .NET implementation installs on a system, which may include application framework APIs (for example,
ASP.NET, WinForms). For package-based target frameworks (such as .NET Standard and .NET Core), the framework
APIs are defined by the packages installed in the app or library. In that case, the target framework implicitly
specifies a metapackage that references all the packages that together make up the framework.
See Target Frameworks.

TFM
Target framework moniker.
A standardized token format for specifying the target framework of a .NET app or library. Target frameworks are
typically referenced by a short name, such as net462 . Long-form TFMs (such as .NETFramework,Version=4.6.2)
exist but are not generally used to specify a target framework.
See Target Frameworks.

UWP
Universal Windows Platform.
An implementation of .NET that is used for building modern, touch-enabled Windows applications and software for
the Internet of Things (IoT). It's designed to unify the different types of devices that you may want to target,
including PCs, tablets, phablets, phones, and even the Xbox. UWP provides many services, such as a centralized app
store, an execution environment (AppContainer), and a set of Windows APIs to use instead of Win32 (WinRT). Apps
can be written in C++, C#, VB.NET, and JavaScript. When using C# and VB.NET, the .NET APIs are provided by .NET
Core.

See also
.NET Guide
.NET Framework Guide
.NET Core
ASP.NET Overview
ASP.NET Core Overview
Choosing between .NET Core and .NET Framework
for server apps
8/17/2017 • 6 min to read • Edit Online

There are two supported implementations for building server-side applications with .NET: .NET Framework and
.NET Core. Both share many of the same components and you can share code across the two. However, there are
fundamental differences between the two and your choice depends on what you want to accomplish. This article
provides guidance on when to use each.
Use .NET Core for your server application when:
You have cross-platform needs.
You are targeting microservices.
You are using Docker containers.
You need high-performance and scalable systems.
You need side-by-side .NET versions per application.
Use .NET Framework for your server application when:
Your app currently uses .NET Framework (recommendation is to extend instead of migrating).
Your app uses third-party .NET libraries or NuGet packages not available for .NET Core.
Your app uses .NET technologies that aren't available for .NET Core.
Your app uses a platform that doesn’t support .NET Core.

When to choose .NET Core


The following sections give a more detailed explanation of the previously stated reasons for picking .NET Core.
Cross-platform needs
If your application (web/service) needs to run on multiple platforms (Windows, Linux, and macOS), use .NET Core.
.NET Core supports the previously mentioned operating systems as your development workstation. Visual Studio
provides an Integrated Development Environment (IDE) for Windows and Mac. You can also use Visual Studio
Code, which runs on macOS, Linux, and Windows. Visual Studio Code supports .NET Core, including IntelliSense
and debugging. Most third-party editors, such as Sublime, Emacs, and VI, work with .NET Core. These third-party
editors get editor IntelliSense using Omnisharp. You can also avoid any code editor and directly use the .NET Core
CLI tools, available for all supported platforms.
Microservices architecture
A microservices architecture allows a mix of technologies across a service boundary. This technology mix enables a
gradual embrace of .NET Core for new microservices that work with other microservices or services. For example,
you can mix microservices or services developed with .NET Framework, Java, Ruby, or other monolithic
technologies.
There are many infrastructure platforms available. Azure Service Fabric is designed for large and complex
microservice systems. Azure App Service is a good choice for stateless microservices. Microservices alternatives
based on Docker fit any kind of microservices approach, as explained in the Containers section. All these platforms
support .NET Core and make them ideal for hosting your microservices.
For more information about microservices architecture, see .NET Microservices. Architecture for Containerized .NET
Applications.
Containers
Containers are commonly used in conjunction with a microservices architecture. Containers can also be used to
containerize web apps or services that follow any architectural pattern. .NET Framework can be used on Windows
containers, but the modularity and lightweight nature of .NET Core makes it a better choice for containers. When
creating and deploying a container, the size of its image is much smaller with .NET Core than with .NET Framework.
Because it's cross-platform, you can deploy server apps to Linux Docker containers, for example.
Docker containers can be hosted in your own Linux or Windows infrastructure, or in a cloud service such as Azure
Container Service. Azure Container Service can manage, orchestrate, and scale container-based applications in the
cloud.
A need for high-performance and scalable systems
When your system needs the best possible performance and scalability, .NET Core and ASP.NET Core are your best
options. High-performance server runtime for Windows Server and Linux makes .NET a top performing web
framework on TechEmpower benchmarks.
Performance and scalability are especially relevant for microservices architectures, where hundreds of
microservices may be running. With ASP.NET Core, systems run with a much lower number of servers/Virtual
Machines (VM). The reduced servers/VMs save costs in infrastructure and hosting.
A need for side by side of .NET versions per application level
To install applications with dependencies on different versions of .NET, we recommend .NET Core. .NET Core offers
side-by-side installation of different versions of the .NET Core runtime on the same machine. This side-by-side
installation allows multiple services on the same server, each of them on its own version of .NET Core. It also
lowers risks and saves money in application upgrades and IT operations.

When to choose .NET Framework


.NET Core offers significant benefits for new applications and application patterns. However, the .NET Framework
continues to be the natural choice for many existing scenarios and as such. The .NET Framework isn't replaced by
.NET Core for all server applications.
Current .NET Framework applications
In most cases, you don’t need to migrate your existing applications to .NET Core. Instead, a recommended
approach is to use .NET Core as you extend an existing application, such as writing a new web service in ASP.NET
Core.
A need to use third-party .NET libraries or NuGet packages not available for .NET Core
Libraries are quickly embracing .NET Standard. .NET Standard enables sharing code across all .NET
implementations including .NET Core. With .NET Standard 2.0, this is even easier:
The API surface became much larger.
Introduced a .NET Framework compatibility mode. This compatibility mode allows .NET Standard/.NET Core
projects to reference .NET Framework libraries. To learn more about the compatibility mode, see Announcing
.NET Standard 2.0.
So only in cases where the libraries or NuGet packages use technologies that aren't available in .NET
Standard/.NET Core, you need to use the .NET Framework.
A need to use .NET technologies not available for .NET Core
Some .NET Framework technologies aren't available in .NET Core. Some of them might be available in later .NET
Core releases. Others don’t apply to the new application patterns targeted by .NET Core and may never be
available. The following list shows the most common technologies not found in .NET Core:
ASP.NET Web Forms applications: ASP.NET Web Forms are only available in the .NET Framework. ASP.NET
Core cannot be used for ASP.NET Web Forms. There are no plans to bring ASP.NET Web Forms to .NET
Core.
ASP.NET Web Pages applications: ASP.NET Web Pages aren't included in ASP.NET Core. ASP.NET Core Razor
Pages have many similarities with Web Pages.
ASP.NET SignalR server/client implementation. Currently, ASP.NET SignalR isn't available for ASP.NET Core
(not client or server). ASP.NET Core SignalR is scheduled for ASP.NET Core 2.1. See the ASP.NET Core
Schedule and Roadmap. Preview state is available at the Server-side and Client Library GitHub repositories.
WCF services implementation. Even when there’s a WCF-Client library to consume WCF services from .NET
Core, WCF server implementation is currently only available in the .NET Framework. This scenario is not part
of the current plan for .NET Core but it’s being considered for the future.
Workflow-related services: Windows Workflow Foundation (WF), Workflow Services (WCF + WF in a single
service) and WCF Data Services (formerly known as "ADO.NET Data Services") are only available in the .NET
Framework. There are no plans to bring WF/WCF+WF/WCF Data Services to .NET Core.
Windows Presentation Foundation (WPF) and Windows Forms: WPF and Windows Forms applications are
only available in the .NET Framework. There are no plans to port them to .NET Core.
Language support: Visual Basic and F# are currently supported in .NET Core, but not for all project types. For
a list of supported project templates, see Template options for dotnet new.
In addition to the official roadmap, there are other frameworks to be ported to .NET Core. For a full list, see the
CoreFX issues marked as port-to-core. This list doesn’t represent a commitment from Microsoft to bring those
components to .NET Core. They're simply capturing the desire from the community to do so. If you care about any
of the components marked as port-to-core , participate in the discussions on GitHub. And if you think something
is missing, file a new issue in the CoreFX repository.
A need to use a platform that doesn’t support .NET Core
Some Microsoft or third-party platforms don’t support .NET Core. For example, some Azure services such as
Service Fabric Stateful Reliable Services and Service Fabric Reliable Actors require .NET Framework. Some other
services provide an SDK not yet available for consumption on .NET Core. This is a transitional circumstance, as all
of Azure services use .NET Core. In the meantime, you can always use the equivalent REST API instead of the client
SDK.

See also
Choose between ASP.NET and ASP.NET Core
.NET Core Guide
Porting from .NET Framework to .NET Core
.NET Framework on Docker Guide
.NET Components Overview
.NET Microservices. Architecture for Containerized .NET Applications
What is "managed code"?
8/5/2017 • 2 min to read • Edit Online

When working with .NET Framework, you will often encounter the term "managed code". This document will
explain what this term means and additional information around it.
To put it very simply, managed code is just that: code whose execution is managed by a runtime. In this case, the
runtime in question is called the Common Language Runtime or CLR, regardless of the implementation (Mono
or .NET Framework or .NET Core). CLR is in charge of taking the managed code, compiling it into machine code and
then executing it. On top of that, runtime provides several important services such as automatic memory
management, security boundaries, type safety etc.
Contrast this to the way you would run a C/C++ program, also called "unmanaged code". In the unmanaged world,
the programmer is in charge of pretty much everything. The actual program is, essentially, a binary that the
operating system (OS) loads into memory and starts. Everything else, from memory management to security
considerations are a burden of the programmer.
Managed code is written in one of the high-level languages that can be run on top of .NET, such as C#, Visual Basic,
F# and others. When you compile code written in those languages with their respective compiler, you don’t get
machine code. You get Intermediate Language code which the runtime then compiles and executes. C++ is the
one exception to this rule, as it can also produce native, unmanaged binaries that run on Windows.

Intermediate Language & execution


What is "Intermediate Language" (or IL for short)? It is a product of compilation of code written in high-level .NET
languages. Once you compile your code written in one of these languages, you will get a binary that is made out of
IL. It is important to note that the IL is independent from any specific language that runs on top of the runtime;
there is even a separate specification for it that you can read if you’re so inclined.
Once you produce IL from your high-level code, you will most likely want to run it. This is where the CLR takes over
and starts the process of Just-In-Time compiling, or JIT-ing your code from IL to machine code that can actually
be run on a CPU. In this way, the CLR knows exactly what your code is doing and can effectively manage it.
Intermediate Language is sometimes also called Common Intermediate Language (CIL) or Microsoft Intermediate
Language (MSIL).

Unmanaged code interoperability


Of course, the CLR allows passing the boundaries between managed and unmanaged world, and there is a lot of
code that does that, even in the Base Class Libraries. This is called interoperability or just interop for short. These
provisions would allow you to, for example, wrap up an unmanaged library and call into it. However, it is important
to note that once you do this, when the code passes the boundaries of the runtime, the actual management of the
execution is again in the hand of unmanaged code, and thus falls under the same restrictions.
Similar to this, C# is one language that allows you to use unmanaged constructs such as pointers directly in code
by utilizing what is known as unsafe context which designates a piece of code for which the execution is not
managed by the CLR.

More resources
.NET Framework Conceptual Overview
Unsafe Code and Pointers
Interoperability (C# Programming guide)
Automatic Memory Management
7/29/2017 • 7 min to read • Edit Online

Automatic memory management is one of the services that the Common Language Runtime provides during
Managed Execution. The Common Language Runtime's garbage collector manages the allocation and release of
memory for an application. For developers, this means that you do not have to write code to perform memory
management tasks when you develop managed applications. Automatic memory management can eliminate
common problems, such as forgetting to free an object and causing a memory leak, or attempting to access
memory for an object that has already been freed. This section describes how the garbage collector allocates and
releases memory.

Allocating Memory
When you initialize a new process, the runtime reserves a contiguous region of address space for the process. This
reserved address space is called the managed heap. The managed heap maintains a pointer to the address where
the next object in the heap will be allocated. Initially, this pointer is set to the managed heap's base address. All
reference types are allocated on the managed heap. When an application creates the first reference type, memory is
allocated for the type at the base address of the managed heap. When the application creates the next object, the
garbage collector allocates memory for it in the address space immediately following the first object. As long as
address space is available, the garbage collector continues to allocate space for new objects in this manner.
Allocating memory from the managed heap is faster than unmanaged memory allocation. Because the runtime
allocates memory for an object by adding a value to a pointer, it is almost as fast as allocating memory from the
stack. In addition, because new objects that are allocated consecutively are stored contiguously in the managed
heap, an application can access the objects very quickly.

Releasing Memory
The garbage collector's optimizing engine determines the best time to perform a collection based on the
allocations being made. When the garbage collector performs a collection, it releases the memory for objects that
are no longer being used by the application. It determines which objects are no longer being used by examining the
application's roots. Every application has a set of roots. Each root either refers to an object on the managed heap or
is set to null. An application's roots include static fields, local variables and parameters on a thread's stack, and CPU
registers. The garbage collector has access to the list of active roots that the just-in-time (JIT) compiler and the
runtime maintain. Using this list, it examines an application's roots, and in the process creates a graph that contains
all the objects that are reachable from the roots.
Objects that are not in the graph are unreachable from the application's roots. The garbage collector considers
unreachable objects garbage and will release the memory allocated for them. During a collection, the garbage
collector examines the managed heap, looking for the blocks of address space occupied by unreachable objects. As
it discovers each unreachable object, it uses a memory-copying function to compact the reachable objects in
memory, freeing up the blocks of address spaces allocated to unreachable objects. Once the memory for the
reachable objects has been compacted, the garbage collector makes the necessary pointer corrections so that the
application's roots point to the objects in their new locations. It also positions the managed heap's pointer after the
last reachable object. Note that memory is compacted only if a collection discovers a significant number of
unreachable objects. If all the objects in the managed heap survive a collection, then there is no need for memory
compaction.
To improve performance, the runtime allocates memory for large objects in a separate heap. The garbage collector
automatically releases the memory for large objects. However, to avoid moving large objects in memory, this
memory is not compacted.

Generations and Performance


To optimize the performance of the garbage collector, the managed heap is divided into three generations: 0, 1, and
2. The runtime's garbage collection algorithm is based on several generalizations that the computer software
industry has discovered to be true by experimenting with garbage collection schemes. First, it is faster to compact
the memory for a portion of the managed heap than for the entire managed heap. Secondly, newer objects will
have shorter lifetimes and older objects will have longer lifetimes. Lastly, newer objects tend to be related to each
other and accessed by the application around the same time.
The runtime's garbage collector stores new objects in generation 0. Objects created early in the application's
lifetime that survive collections are promoted and stored in generations 1 and 2. The process of object promotion is
described later in this topic. Because it is faster to compact a portion of the managed heap than the entire heap, this
scheme allows the garbage collector to release the memory in a specific generation rather than release the
memory for the entire managed heap each time it performs a collection.
In reality, the garbage collector performs a collection when generation 0 is full. If an application attempts to create a
new object when generation 0 is full, the garbage collector discovers that there is no address space remaining in
generation 0 to allocate for the object. The garbage collector performs a collection in an attempt to free address
space in generation 0 for the object. The garbage collector starts by examining the objects in generation 0 rather
than all objects in the managed heap. This is the most efficient approach, because new objects tend to have short
lifetimes, and it is expected that many of the objects in generation 0 will no longer be in use by the application
when a collection is performed. In addition, a collection of generation 0 alone often reclaims enough memory to
allow the application to continue creating new objects.
After the garbage collector performs a collection of generation 0, it compacts the memory for the reachable objects
as explained in Releasing Memory earlier in this topic. The garbage collector then promotes these objects and
considers this portion of the managed heap generation 1. Because objects that survive collections tend to have
longer lifetimes, it makes sense to promote them to a higher generation. As a result, the garbage collector does not
have to reexamine the objects in generations 1 and 2 each time it performs a collection of generation 0.
After the garbage collector performs its first collection of generation 0 and promotes the reachable objects to
generation 1, it considers the remainder of the managed heap generation 0. It continues to allocate memory for
new objects in generation 0 until generation 0 is full and it is necessary to perform another collection. At this point,
the garbage collector's optimizing engine determines whether it is necessary to examine the objects in older
generations. For example, if a collection of generation 0 does not reclaim enough memory for the application to
successfully complete its attempt to create a new object, the garbage collector can perform a collection of
generation 1, then generation 2. If this does not reclaim enough memory, the garbage collector can perform a
collection of generations 2, 1, and 0. After each collection, the garbage collector compacts the reachable objects in
generation 0 and promotes them to generation 1. Objects in generation 1 that survive collections are promoted to
generation 2. Because the garbage collector supports only three generations, objects in generation 2 that survive a
collection remain in generation 2 until they are determined to be unreachable in a future collection.

Releasing Memory for Unmanaged Resources


For the majority of the objects that your application creates, you can rely on the garbage collector to automatically
perform the necessary memory management tasks. However, unmanaged resources require explicit cleanup. The
most common type of unmanaged resource is an object that wraps an operating system resource, such as a file
handle, window handle, or network connection. Although the garbage collector is able to track the lifetime of a
managed object that encapsulates an unmanaged resource, it does not have specific knowledge about how to clean
up the resource. When you create an object that encapsulates an unmanaged resource, it is recommended that you
provide the necessary code to clean up the unmanaged resource in a public Dispose method. By providing a
Dispose method, you enable users of your object to explicitly free its memory when they are finished with the
object. When you use an object that encapsulates an unmanaged resource, you should be aware of Dispose and
call it as necessary. For more information about cleaning up unmanaged resources and an example of a design
pattern for implementing Dispose, see Garbage Collection.

See Also
GC
Garbage Collection
Managed Execution Process
Common Language Runtime (CLR)
7/29/2017 • 4 min to read • Edit Online

The .NET Framework provides a run-time environment called the common language runtime, which runs the code
and provides services that make the development process easier.
Compilers and tools expose the common language runtime's functionality and enable you to write code that
benefits from this managed execution environment. Code that you develop with a language compiler that targets
the runtime is called managed code; it benefits from features such as cross-language integration, cross-language
exception handling, enhanced security, versioning and deployment support, a simplified model for component
interaction, and debugging and profiling services.

NOTE
Compilers and tools are able to produce output that the common language runtime can consume because the type system,
the format of metadata, and the runtime environment (the virtual execution system) are all defined by a public standard, the
ECMA Common Language Infrastructure specification. For more information, see ECMA C# and Common Language
Infrastructure Specifications.

To enable the runtime to provide services to managed code, language compilers must emit metadata that describes
the types, members, and references in your code. Metadata is stored with the code; every loadable common
language runtime portable executable (PE) file contains metadata. The runtime uses metadata to locate and load
classes, lay out instances in memory, resolve method invocations, generate native code, enforce security, and set
run-time context boundaries.
The runtime automatically handles object layout and manages references to objects, releasing them when they are
no longer being used. Objects whose lifetimes are managed in this way are called managed data. Garbage
collection eliminates memory leaks as well as some other common programming errors. If your code is managed,
you can use managed data, unmanaged data, or both managed and unmanaged data in your .NET Framework
application. Because language compilers supply their own types, such as primitive types, you might not always
know (or need to know) whether your data is being managed.
The common language runtime makes it easy to design components and applications whose objects interact across
languages. Objects written in different languages can communicate with each other, and their behaviors can be
tightly integrated. For example, you can define a class and then use a different language to derive a class from your
original class or call a method on the original class. You can also pass an instance of a class to a method of a class
written in a different language. This cross-language integration is possible because language compilers and tools
that target the runtime use a common type system defined by the runtime, and they follow the runtime's rules for
defining new types, as well as for creating, using, persisting, and binding to types.
As part of their metadata, all managed components carry information about the components and resources they
were built against. The runtime uses this information to ensure that your component or application has the
specified versions of everything it needs, which makes your code less likely to break because of some unmet
dependency. Registration information and state data are no longer stored in the registry where they can be difficult
to establish and maintain. Instead, information about the types you define (and their dependencies) is stored with
the code as metadata, making the tasks of component replication and removal much less complicated.
Language compilers and tools expose the runtime's functionality in ways that are intended to be useful and
intuitive to developers. This means that some features of the runtime might be more noticeable in one
environment than in another. How you experience the runtime depends on which language compilers or tools you
use. For example, if you are a Visual Basic developer, you might notice that with the common language runtime, the
Visual Basic language has more object-oriented features than before. The runtime provides the following benefits:
Performance improvements.
The ability to easily use components developed in other languages.
Extensible types provided by a class library.
Language features such as inheritance, interfaces, and overloading for object-oriented programming.
Support for explicit free threading that allows creation of multithreaded, scalable applications.
Support for structured exception handling.
Support for custom attributes.
Garbage collection.
Use of delegates instead of function pointers for increased type safety and security. For more information
about delegates, see Common Type System.

Versions of the Common Language Runtime


The version number of the .NET Framework doesn't necessarily correspond to the version number of the CLR it
includes. The following table shows how the two version numbers correlate.

.NET FRAMEWORK VERSION INCLUDES CLR VERSION

1.0 1.0

1.1 1.1

2.0 2.0

3.0 2.0

3.5 2.0

4 4

4.5 (including 4.5.1 and 4.5.2) 4

4.6 (including 4.6.1 and 4.6.2) 4

4.7 4

Related Topics
TITLE DESCRIPTION

Managed Execution Process Describes the steps required to take advantage of the
common language runtime.

Automatic Memory Management Describes how the garbage collector allocates and releases
memory.
TITLE DESCRIPTION

NIB: Overview of the .NET Framework Describes key .NET Framework concepts such as the common
type system, cross-language interoperability, managed
execution, application domains, and assemblies.

Common Type System Describes how types are declared, used, and managed in the
runtime in support of cross-language integration.

See Also
Versions and Dependencies
Language independence and language-independent
components
8/5/2017 • 68 min to read • Edit Online

.NET is language independent. This means that, as a developer, you can develop in one of the many languages that
target .NET implementations, such as C#, F#, and Visual Basic. You can access the types and members of class
libraries developed for .NET implementations without having to know the language in which they were originally
written and without having to follow any of the original language's conventions. If you are a component developer,
your component can be accessed by any .NET app regardless of its language.

NOTE
This first part of this article discusses creating language-independent components - that is, components that can be
consumed by apps that are written in any language. You can also create a single component or app from source code written
in multiple languages; see Cross-Language Interoperability in the second part of this article.

To fully interact with other objects written in any language, objects must expose to callers only those features that
are common to all languages. This common set of features is defined by the Common Language Specification
(CLS), which is a set of rules that apply to generated assemblies. The Common Language Specification is defined in
Partition I, Clauses 7 through 11 of the ECMA-335 Standard: Common Language Infrastructure.
If your component conforms to the Common Language Specification, it is guaranteed to be CLS-compliant and can
be accessed from code in assemblies written in any programming language that supports the CLS. You can
determine whether your component conforms to the Common Language Specification at compile time by applying
the CLSCompliantAttribute attribute to your source code. For more information, see The CLSCompliantAttribute
attribute.
In this article:
CLS compliance rules
Types and type member signatures
Naming conventions
Type conversion
Arrays
Interfaces
Enumerations
Type members in general
Member accessibility
Generic types and members
Constructors
Properties
Events
Overloads
Exceptions
Attributes
CLSCompliantAttribute attribute
Cross-Language Interoperability

CLS compliance rules


This section discusses the rules for creating a CLS-compliant component. For a complete list of rules, see Partition I,
Clause 11 of the ECMA-335 Standard: Common Language Infrastructure.

NOTE
The Common Language Specification discusses each rule for CLS compliance as it applies to consumers (developers who are
programmatically accessing a component that is CLS-compliant), frameworks (developers who are using a language compiler
to create CLS-compliant libraries), and extenders (developers who are creating a tool such as a language compiler or a code
parser that creates CLS-compliant components). This article focuses on the rules as they apply to frameworks. Note, though,
that some of the rules that apply to extenders may also apply to assemblies that are created using Reflection.Emit.

To design a component that is language independent, you only need to apply the rules for CLS compliance to your
component's public interface. Your private implementation does not have to conform to the specification.

IMPORTANT
The rules for CLS compliance apply only to a component's public interface, not to its private implementation.

For example, unsigned integers other than Byte are not CLS-compliant. Because the Person class in the following
example exposes an Age property of type UInt16, the following code displays a compiler warning.

using System;

[assembly: CLSCompliant(true)]

public class Person


{
private UInt16 personAge = 0;

public UInt16 Age


{ get { return personAge; } }
}
// The attempt to compile the example displays the following compiler warning:
// Public1.cs(10,18): warning CS3003: Type of 'Person.Age' is not CLS-compliant
<Assembly: CLSCompliant(True)>

Public Class Person


Private personAge As UInt16

Public ReadOnly Property Age As UInt16


Get
Return personAge
End Get
End Property
End Class
' The attempt to compile the example displays the following compiler warning:
' Public1.vb(9) : warning BC40027: Return type of function 'Age' is not CLS-compliant.
'
' Public ReadOnly Property Age As UInt16
' ~~~

You can make the Person class CLS-compliant by changing the type of Age property from UInt16 to Int16, which
is a CLS-compliant, 16-bit signed integer. You do not have to change the type of the private personAge field.

using System;

[assembly: CLSCompliant(true)]

public class Person


{
private Int16 personAge = 0;

public Int16 Age


{ get { return personAge; } }
}

<Assembly: CLSCompliant(True)>

Public Class Person


Private personAge As UInt16

Public ReadOnly Property Age As Int16


Get
Return CType(personAge, Int16)
End Get
End Property
End Class

A library's public interface consists of the following:


Definitions of public classes.
Definitions of the public members of public classes, and definitions of members accessible to derived classes
(that is, protected members).
Parameters and return types of public methods of public classes, and parameters and return types of
methods accessible to derived classes.
The rules for CLS compliance are listed in the following table. The text of the rules is taken verbatim from the
ECMA-335 Standard: Common Language Infrastructure, which is Copyright 2012 by Ecma International. More
detailed information about these rules is found in the following sections.
CATEGORY SEE RULE RULE NUMBER

Accessibility Member accessibility Accessibility shall not be 10


changed when overriding
inherited methods, except
when overriding a method
inherited from a different
assembly with accessibility
family-or-assembly . In
this case, the override shall
have accessibility family .

Accessibility Member accessibility The visibility and accessibility 12


of types and members shall
be such that types in the
signature of any member
shall be visible and accessible
whenever the member itself
is visible and accessible. For
example, a public method
that is visible outside its
assembly shall not have an
argument whose type is
visible only within the
assembly. The visibility and
accessibility of types
composing an instantiated
generic type used in the
signature of any member
shall be visible and accessible
whenever the member itself
is visible and accessible. For
example, an instantiated
generic type present in the
signature of a member that
is visible outside its assembly
shall not have a generic
argument whose type is
visible only within the
assembly.

Arrays Arrays Arrays shall have elements 16


with a CLS-compliant type,
and all dimensions of the
array shall have lower
bounds of zero. Only the fact
that an item is an array and
the element type of the
array shall be required to
distinguish between
overloads. When overloading
is based on two or more
array types the element
types shall be named types.

Attributes Attributes Attributes shall be of type 41


System.Attribute, or a type
inheriting from it.
CATEGORY SEE RULE RULE NUMBER

Attributes Attributes The CLS only allows a subset 34


of the encodings of custom
attributes. The only types
that shall appear in these
encodings are (see Partition
IV): System.Type,
System.String, System.Char,
System.Boolean,
System.Byte, System.Int16,
System.Int32, System.Int64,
System.Single,
System.Double, and any
enumeration type based on
a CLS-compliant base
integer type.

Attributes Attributes The CLS does not allow 35


publicly visible required
modifiers ( modreq , see
Partition II), but does allow
optional modifiers ( modopt ,
see Partition II) it does not
understand.

Constructors Constructors An object constructor shall 21


call some instance
constructor of its base class
before any access occurs to
inherited instance data. (This
does not apply to value
types, which need not have
constructors.)

Constructors Constructors An object constructor shall 22


not be called except as part
of the creation of an object,
and an object shall not be
initialized twice.

Enumerations Enumerations The underlying type of an 7


enum shall be a built-in CLS
integer type, the name of
the field shall be "value__",
and that field shall be
marked RTSpecialName .
CATEGORY SEE RULE RULE NUMBER

Enumerations Enumerations There are two distinct kinds 8


of enums, indicated by the
presence or absence of the
System.FlagsAttribute (see
Partition IV Library) custom
attribute. One represents
named integer values; the
other represents named bit
flags that can be combined
to generate an unnamed
value. The value of an enum
is not limited to the specified
values.

Enumerations Enumerations Literal static fields of an 9


enum shall have the type of
the enum itself.

Events Events The methods that implement 29


an event shall be marked
SpecialName in the
metadata.

Events Events The accessibility of an event 30


and of its accessors shall be
identical.

Events Events The add and remove 31


methods for an event shall
both either be present or
absent.

Events Events The add and remove 32


methods for an event shall
each take one parameter
whose type defines the type
of the event and that shall
be derived from
System.Delegate.

Events Events Events shall adhere to a 33


specific naming pattern. The
SpecialName attribute
referred to in CLS rule 29
shall be ignored in
appropriate name
comparisons and shall
adhere to identifier rules.

Exceptions Exceptions Objects that are thrown shall 40


be of type System.Exception
or a type inheriting from it.
Nonetheless, CLS-compliant
methods are not required to
block the propagation of
other types of exceptions.
CATEGORY SEE RULE RULE NUMBER

General CLS compliance rules CLS rules apply only to those 1


parts of a type that are
accessible or visible outsideof
the defining assembly.

General CLS compliance rules Members of non-CLS 2


compliant types shall not be
marked CLS-compliant.

Generics Generic types and members Nested types shall have at 42


least as many generic
parameters as the enclosing
type. Generic parameters in
a nested type correspond by
position to the generic
parameters in its enclosing
type.

Generics Generic types and members The name of a generic type 43


shall encode the number of
type parameters declared on
the non-nested type, or
newly introduced to the type
if nested, according to the
rules defined above.

Generics Generic types and members A generic type shall redeclare 44


sufficient constraints to
guarantee that any
constraints on the base type,
or interfaces would be
satisfied by the generic type
constraints.

Generics Generic types and members Types used as constraints on 45


generic parameters shall
themselves be CLS-
compliant.

Generics Generic types and members The visibility and accessibility 46


of members (including
nested types) in an
instantiated generic type
shall be considered to be
scoped to the specific
instantiation rather than the
generic type declaration as a
whole. Assuming this, the
visibility and accessibility
rules of CLS rule 12 still
apply.

Generics Generic types and members For each abstract or virtual 47


generic method, there shall
be a default concrete
(nonabstract)
implementation
CATEGORY SEE RULE RULE NUMBER

Interfaces Interfaces CLS-compliant interfaces 18


shall not require the
definition of non-CLS
compliantmethods in order
to implement them.

Interfaces Interfaces CLS-compliant interfaces 19


shall not define static
methods, nor shall they
define fields.

Members Type members in general Global static fields and 36


methods are not CLS-
compliant.

Members -- The value of a literal static is 13


specified through the use of
field initialization metadata.
A CLS-compliant literal must
have a value specified in field
initialization metadata that is
of exactly the same type as
the literal (or of the
underlying type, if that literal
is an enum ).

Members Type members in general The vararg constraint is not 15


part of the CLS, and the only
calling convention supported
by the CLS is the standard
managed calling convention.

Naming conventions Naming conventions Assemblies shall follow 4


Annex 7 of Technical Report
15 of the Unicode
Standard3.0 governing the
set of characters permitted
to start and be included in
identifiers, available online at
Unicode Normalization
Forms. Identifiers shall be in
the canonical format defined
by Unicode Normalization
Form C. For CLS purposes,
two identifiersare the same if
their lowercase mappings (as
specified by the Unicode
locale-insensitive, one-to-
one lowercase mappings) are
the same. That is, for two
identifiers to be considered
different under the CLS they
shall differ in more than
simply their case. However,
in order to override an
inherited definition the CLI
requires the precise
encoding of the original
declaration be used.
CATEGORY SEE RULE RULE NUMBER

Overloading Naming conventions All names introduced in a 5


CLS-compliant scope shall be
distinct independent of kind,
except where the names are
identical and resolved via
overloading. That is, while
the CTS allows a single type
to use the same name for a
method and a field, the CLS
does not.

Overloading Naming conventions Fields and nested types shall 6


be distinct by identifier
comparison alone,
eventhough the CTS allows
distinct signatures to be
distinguished. Methods,
properties, and events that
have the same name (by
identifier comparison) shall
differ by more than just the
return type,except as
specified in CLS Rule 39

Overloading Overloads Only properties and 37


methods can be overloaded.
CATEGORY SEE RULE RULE NUMBER

Overloading Overloads Properties and methods can 38


be overloaded based only on
the number and types of
their parameters, except the
conversion operators named
op_Implicit and
op_Explicit , which can
also be overloaded based on
their return type.

Overloading -- If two or more CLS- 48


compliant methods declared
in a type have the same
nameand, for a specific set of
type instantiations, they
have the same parameter
and return types, then all
these methods shall be
semantically equivalent at
those type instantiations.

Properties Properties The methods that implement 24


the getter and setter
methods of a property shall
be marked SpecialName in
the metadata.

Properties Properties A property’s accessors shall 26


all be static, all be virtual, or
all be instance.

Properties Properties The type of a property shall 27


be the return type of the
getter and the type of the
last argument of the setter.
The types of the parameters
of the property shall be the
types of the parameters to
the getter and the types of
all but the final parameter of
the setter. All of these types
shall be CLS-compliant, and
shall not be managed
pointers (that is, shall not be
passed by reference).

Properties Properties Properties shall adhere to a 28


specific naming pattern. The
SpecialName attribute
referred to in CLS rule 24
shall be ignored in
appropriate name
comparisons and shall
adhere to identifier rules. A
property shall have a getter
method, a setter method, or
both.
CATEGORY SEE RULE RULE NUMBER

Type conversion Type conversion If either op_Implicit or 39


op_Explicit is provided, an
alternate means of providing
the coercion shall be
provided.

Types Types and type member Boxed value types are not 3
signatures CLS-compliant.

Types Types and type member All types appearing in a 11


signatures signature shall be CLS-
compliant. All types
composing an instantiated
generic type shall be CLS-
compliant.

Types Types and type member Typed references are not 14


signatures CLS-compliant.

Types Types and type member Unmanaged pointer types 17


signatures are not CLS-compliant.

Types Types and type member CLS-compliant classes, value 20


signatures types, and interfaces shall
not require the
implementation of non-CLS-
compliant members

Types Types and type member System.Object is CLS- 23


signatures compliant. Any other CLS-
compliant class shall inherit
from a CLS-compliant class.

Types and type member signatures


The System.Object type is CLS-compliant and is the base type of all object types in the .NET Framework type
system. Inheritance in the .NET Framework is either implicit (for example, the String class implicitly inherits from
the Object class) or explicit (for example, the CultureNotFoundException class explicitly inherits from the
ArgumentException class, which explicitly inherits from the Exception class. For a derived type to be CLS compliant,
its base type must also be CLS-compliant.
The following example shows a derived type whose base type is not CLS-compliant. It defines a base Counter class
that uses an unsigned 32-bit integer as a counter. Because the class provides counter functionality by wrapping an
unsigned integer, the class is marked as non-CLS-compliant. As a result, a derived class, NonZeroCounter , is also not
CLS-compliant.
using System;

[assembly: CLSCompliant(true)]

[CLSCompliant(false)]
public class Counter
{
UInt32 ctr;

public Counter()
{
ctr = 0;
}

protected Counter(UInt32 ctr)


{
this.ctr = ctr;
}

public override string ToString()


{
return String.Format("{0}). ", ctr);
}

public UInt32 Value


{
get { return ctr; }
}

public void Increment()


{
ctr += (uint) 1;
}
}

public class NonZeroCounter : Counter


{
public NonZeroCounter(int startIndex) : this((uint) startIndex)
{
}

private NonZeroCounter(UInt32 startIndex) : base(startIndex)


{
}
}
// Compilation produces a compiler warning like the following:
// Type3.cs(37,14): warning CS3009: 'NonZeroCounter': base type 'Counter' is not
// CLS-compliant
// Type3.cs(7,14): (Location of symbol related to previous warning)
<Assembly: CLSCompliant(True)>

<CLSCompliant(False)> _
Public Class Counter
Dim ctr As UInt32

Public Sub New


ctr = 0
End Sub

Protected Sub New(ctr As UInt32)


ctr = ctr
End Sub

Public Overrides Function ToString() As String


Return String.Format("{0}). ", ctr)
End Function

Public ReadOnly Property Value As UInt32


Get
Return ctr
End Get
End Property

Public Sub Increment()


ctr += CType(1, UInt32)
End Sub
End Class

Public Class NonZeroCounter : Inherits Counter


Public Sub New(startIndex As Integer)
MyClass.New(CType(startIndex, UInt32))
End Sub

Private Sub New(startIndex As UInt32)


MyBase.New(CType(startIndex, UInt32))
End Sub
End Class
' Compilation produces a compiler warning like the following:
' Type3.vb(34) : warning BC40026: 'NonZeroCounter' is not CLS-compliant
' because it derives from 'Counter', which is not CLS-compliant.
'
' Public Class NonZeroCounter : Inherits Counter
' ~~~~~~~~~~~~~~

All types that appear in member signatures, including a method's return type or a property type, must be CLS-
compliant. In addition, for generic types:
All types that compose an instantiated generic type must be CLS-compliant.
All types used as constraints on generic parameters must be CLS-compliant.
The .NET common type system includes a number of built-in types that are supported directly by the common
language runtime and are specially encoded in an assembly's metadata. Of these intrinsic types, the types listed in
the following table are CLS-compliant.

CLS-COMPLIANT TYPE DESCRIPTION

Byte 8-bit unsigned integer

Int16 16-bit signed integer


CLS-COMPLIANT TYPE DESCRIPTION

Int32 32-bit signed integer

Int64 64-bit signed integer

Single Single-precision floating-point value

Double Double-precision floating-point value

Boolean true or false value type

Char UTF-16 encoded code unit

Decimal Non-floating-point decimal number

IntPtr Pointer or handle of a platform-defined size

String Collection of zero, one, or more Char objects

The intrinsic types listed in the following table are not CLS-Compliant.

NON-COMPLIANT TYPE DESCRIPTION CLS-COMPLIANT ALTERNATIVE

SByte 8-bit signed integer data type Int16

UInt16 16-bit unsigned integer Int32

UInt32 32-bit unsigned integer Int64

UInt64 64-bit unsigned integer Int64 (may overflow), BigInteger, or


Double

UIntPtr Unsigned pointer or handle IntPtr

The .NET Framework Class Library or any other class library may include other types that aren't CLS-compliant; for
example:
Boxed value types. The following C# example creates a class that has a public property of type int * named
Value . Because an int * is a boxed value type, the compiler flags it as non-CLS-compliant.
using System;

[assembly:CLSCompliant(true)]

public unsafe class TestClass


{
private int* val;

public TestClass(int number)


{
val = (int*) number;
}

public int* Value {


get { return val; }
}
}
// The compiler generates the following output when compiling this example:
// warning CS3003: Type of 'TestClass.Value' is not CLS-compliant

Typed references, which are special constructs that contain a reference to an object and a reference to a type.
If a type is not CLS-compliant, you should apply the CLSCompliantAttribute attribute with an isCompliant
parameter with a value of false to it. For more information, see the CLSCompliantAttribute attribute section.
The following example illustrates the problem of CLS compliance in a method signature and in generic type
instantiation. It defines an InvoiceItem class with a property of type UInt32, a property of type Nullable(Of UInt32),
and a constructor with parameters of type UInt32 and Nullable(Of UInt32) . You get four compiler warnings when
you try to compile this example.

using System;

[assembly: CLSCompliant(true)]

public class InvoiceItem


{
private uint invId = 0;
private uint itemId = 0;
private Nullable<uint> qty;

public InvoiceItem(uint sku, Nullable<uint> quantity)


{
itemId = sku;
qty = quantity;
}

public Nullable<uint> Quantity


{
get { return qty; }
set { qty = value; }
}

public uint InvoiceId


{
get { return invId; }
set { invId = value; }
}
}
// The attempt to compile the example displays the following output:
// Type1.cs(13,23): warning CS3001: Argument type 'uint' is not CLS-compliant
// Type1.cs(13,33): warning CS3001: Argument type 'uint?' is not CLS-compliant
// Type1.cs(19,26): warning CS3003: Type of 'InvoiceItem.Quantity' is not CLS-compliant
// Type1.cs(25,16): warning CS3003: Type of 'InvoiceItem.InvoiceId' is not CLS-compliant
<Assembly: CLSCompliant(True)>

Public Class InvoiceItem

Private invId As UInteger = 0


Private itemId As UInteger = 0
Private qty AS Nullable(Of UInteger)

Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))


itemId = sku
qty = quantity
End Sub

Public Property Quantity As Nullable(Of UInteger)


Get
Return qty
End Get
Set
qty = value
End Set
End Property

Public Property InvoiceId As UInteger


Get
Return invId
End Get
Set
invId = value
End Set
End Property
End Class
' The attempt to compile the example displays output similar to the following:
' Type1.vb(13) : warning BC40028: Type of parameter 'sku' is not CLS-compliant.
'
' Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))
' ~~~
' Type1.vb(13) : warning BC40041: Type 'UInteger' is not CLS-compliant.
'
' Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))
' ~~~~~~~~
' Type1.vb(18) : warning BC40041: Type 'UInteger' is not CLS-compliant.
'
' Public Property Quantity As Nullable(Of UInteger)
' ~~~~~~~~
' Type1.vb(27) : warning BC40027: Return type of function 'InvoiceId' is not CLS-compliant.
'
' Public Property InvoiceId As UInteger

To eliminate the compiler warnings, replace the non-CLS-compliant types in the InvoiceItem public interface with
compliant types:
using System;

[assembly: CLSCompliant(true)]

public class InvoiceItem


{
private uint invId = 0;
private uint itemId = 0;
private Nullable<int> qty;

public InvoiceItem(int sku, Nullable<int> quantity)


{
if (sku <= 0)
throw new ArgumentOutOfRangeException("The item number is zero or negative.");
itemId = (uint) sku;

qty = quantity;
}

public Nullable<int> Quantity


{
get { return qty; }
set { qty = value; }
}

public int InvoiceId


{
get { return (int) invId; }
set {
if (value <= 0)
throw new ArgumentOutOfRangeException("The invoice number is zero or negative.");
invId = (uint) value; }
}
}
Assembly: CLSCompliant(True)>

Public Class InvoiceItem

Private invId As UInteger = 0


Private itemId As UInteger = 0
Private qty AS Nullable(Of Integer)

Public Sub New(sku As Integer, quantity As Nullable(Of Integer))


If sku <= 0 Then
Throw New ArgumentOutOfRangeException("The item number is zero or negative.")
End If
itemId = CUInt(sku)
qty = quantity
End Sub

Public Property Quantity As Nullable(Of Integer)


Get
Return qty
End Get
Set
qty = value
End Set
End Property

Public Property InvoiceId As Integer


Get
Return CInt(invId)
End Get
Set
invId = CUInt(value)
End Set
End Property
End Class

In addition to the specific types listed, some categories of types are not CLS compliant. These include unmanaged
pointer types and function pointer types. The following example generates a compiler warning because it uses a
pointer to an integer to create an array of integers.

using System;

[assembly: CLSCompliant(true)]

public class ArrayHelper


{
unsafe public static Array CreateInstance(Type type, int* ptr, int items)
{
Array arr = Array.CreateInstance(type, items);
int* addr = ptr;
for (int ctr = 0; ctr < items; ctr++) {
int value = *addr;
arr.SetValue(value, ctr);
addr++;
}
return arr;
}
}
// The attempt to compile this example displays the following output:
// UnmanagedPtr1.cs(8,57): warning CS3001: Argument type 'int*' is not CLS-compliant
using System;

[assembly: CLSCompliant(true)]

public class ArrayHelper


{
unsafe public static Array CreateInstance(Type type, int* ptr, int items)
{
Array arr = Array.CreateInstance(type, items);
int* addr = ptr;
for (int ctr = 0; ctr < items; ctr++) {
int value = *addr;
arr.SetValue(value, ctr);
addr++;
}
return arr;
}
}
// The attempt to compile this example displays the following output:
// UnmanagedPtr1.cs(8,57): warning CS3001: Argument type 'int*' is not CLS-compliant

For CLS-compliant abstract classes (that is, classes marked as abstract in C#), all members of the class must also
be CLS-compliant.
Naming conventions
Because some programming languages are case-insensitive, identifiers (such as the names of namespaces, types,
and members) must differ by more than case. Two identifiers are considered equivalent if their lowercase
mappings are the same. The following C# example defines two public classes, Person and person . Because they
differ only by case, the C# compiler flags them as not CLS-compliant.

using System;

[assembly: CLSCompliant(true)]

public class Person : person


{

public class person


{

}
// Compilation produces a compiler warning like the following:
// Naming1.cs(11,14): warning CS3005: Identifier 'person' differing
// only in case is not CLS-compliant
// Naming1.cs(6,14): (Location of symbol related to previous warning)

Programming language identifiers, such as the names of namespaces, types, and members, must conform to the
Unicode Standard 3.0, Technical Report 15, Annex 7. This means that:
The first character of an identifier can be any Unicode uppercase letter, lowercase letter, title case letter,
modifier letter, other letter, or letter number. For information on Unicode character categories, see the
System.Globalization.UnicodeCategory enumeration.
Subsequent characters can be from any of the categories as the first character, and can also include non-
spacing marks, spacing combining marks, decimal numbers, connector punctuations, and formatting codes.
Before you compare identifiers, you should filter out formatting codes and convert the identifiers to Unicode
Normalization Form C, because a single character can be represented by multiple UTF-16-encoded code units.
Character sequences that produce the same code units in Unicode Normalization Form C are not CLS-compliant.
The following example defines a property named Å , which consists of the character ANGSTROM SIGN (U+212B),
and a second property named Å which consists of the character LATIN CAPITAL LETTER A WITH RING ABOVE
(U+00C5). The C# compiler flags the source code as non-CLS-compliant.

public class Size


{
private double a1;
private double a2;

public double Å
{
get { return a1; }
set { a1 = value; }
}

public double Å
{
get { return a2; }
set { a2 = value; }
}
}
// Compilation produces a compiler warning like the following:
// Naming2a.cs(16,18): warning CS3005: Identifier 'Size.Å' differing only in case is not
// CLS-compliant
// Naming2a.cs(10,18): (Location of symbol related to previous warning)
// Naming2a.cs(18,8): warning CS3005: Identifier 'Size.Å.get' differing only in case is not
// CLS-compliant
// Naming2a.cs(12,8): (Location of symbol related to previous warning)
// Naming2a.cs(19,8): warning CS3005: Identifier 'Size.Å.set' differing only in case is not
// CLS-compliant
// Naming2a.cs(13,8): (Location of symbol related to previous warning)

<Assembly: CLSCompliant(True)>
Public Class Size
Private a1 As Double
Private a2 As Double

Public Property Å As Double


Get
Return a1
End Get
Set
a1 = value
End Set
End Property

Public Property Å As Double


Get
Return a2
End Get
Set
a2 = value
End Set
End Property
End Class
' Compilation produces a compiler warning like the following:
' Naming1.vb(9) : error BC30269: 'Public Property Å As Double' has multiple definitions
' with identical signatures.
'
' Public Property Å As Double
' ~

Member names within a particular scope (such as the namespaces within an assembly, the types within a
namespace, or the members within a type) must be unique except for names that are resolved through
overloading. This requirement is more stringent than that of the common type system, which allows multiple
members within a scope to have identical names as long as they are different kinds of members (for example, one
is a method and one is a field). In particular, for type members:
Fields and nested types are distinguished by name alone.
Methods, properties, and events that have the same name must differ by more than just return type.
The following example illustrates the requirement that member names must be unique within their scope. It defines
a class named Converter that includes four members named Conversion . Three are methods, and one is a
property. The method that includes an Int64 parameter is uniquely named, but the two methods with an Int32
parameter are not, because return value is not considered a part of a member's signature. The Conversion property
also violates this requirement, because properties cannot have the same name as overloaded methods.

using System;

[assembly: CLSCompliant(true)]

public class Converter


{
public double Conversion(int number)
{
return (double) number;
}

public float Conversion(int number)


{
return (float) number;
}

public double Conversion(long number)


{
return (double) number;
}

public bool Conversion


{
get { return true; }
}
}
// Compilation produces a compiler error like the following:
// Naming3.cs(13,17): error CS0111: Type 'Converter' already defines a member called
// 'Conversion' with the same parameter types
// Naming3.cs(8,18): (Location of symbol related to previous error)
// Naming3.cs(23,16): error CS0102: The type 'Converter' already contains a definition for
// 'Conversion'
// Naming3.cs(8,18): (Location of symbol related to previous error)
<Assembly: CLSCompliant(True)>

Public Class Converter


Public Function Conversion(number As Integer) As Double
Return CDbl(number)
End Function

Public Function Conversion(number As Integer) As Single


Return CSng(number)
End Function

Public Function Conversion(number As Long) As Double


Return CDbl(number)
End Function

Public ReadOnly Property Conversion As Boolean


Get
Return True
End Get
End Property
End Class
' Compilation produces a compiler error like the following:
' Naming3.vb(8) : error BC30301: 'Public Function Conversion(number As Integer) As Double'
' and 'Public Function Conversion(number As Integer) As Single' cannot
' overload each other because they differ only by return types.
'
' Public Function Conversion(number As Integer) As Double
' ~~~~~~~~~~
' Naming3.vb(20) : error BC30260: 'Conversion' is already declared as 'Public Function
' Conversion(number As Integer) As Single' in this class.
'
' Public ReadOnly Property Conversion As Boolean
' ~~~~~~~~~~

Individual languages include unique keywords, so languages that target the common language runtime must also
provide some mechanism for referencing identifiers (such as type names) that coincide with keywords. For
example, case is a keyword in both C# and Visual Basic. However, the following Visual Basic example is able to
disambiguate a class named case from the case keyword by using opening and closing braces. Otherwise, the
example would produce the error message, "Keyword is not valid as an identifier," and fail to compile.

Public Class [case]


Private _id As Guid
Private name As String

Public Sub New(name As String)


_id = Guid.NewGuid()
Me.name = name
End Sub

Public ReadOnly Property ClientName As String


Get
Return name
End Get
End Property
End Class

The following C# example is able to instantiate the case class by using the @ symbol to disambiguate the
identifier from the language keyword. Without it, the C# compiler would display two error messages, "Type
expected" and "Invalid expression term 'case'."
using System;

public class Example


{
public static void Main()
{
@case c = new @case("John");
Console.WriteLine(c.ClientName);
}
}

Type conversion
The Common Language Specification defines two conversion operators:
op_Implicit, which is used for widening conversions that do not result in loss of data or precision. For
example, the Decimal structure includes an overloaded op_Implicit operator to convert values of integral
types and Char values to Decimal values.
op_Explicit , which is used for narrowing conversions that can result in loss of magnitude (a value is
converted to a value that has a smaller range) or precision. For example, the Decimal structure includes an
overloaded op_Explicit operator to convert Double and Single values to Decimal and to convert Decimal
values to integral values, Double , Single , and Char .
However, not all languages support operator overloading or the definition of custom operators. If you choose to
implement these conversion operators, you should also provide an alternate way to perform the conversion. We
recommend that you provide From Xxx and To Xxx methods.
The following example defines CLS-compliant implicit and explicit conversions. It creates a UDouble class that
represents an signed double-precision, floating-point number. It provides for implicit conversions from UDouble to
Double and for explicit conversions from UDouble to Single , Double to UDouble , and Single to UDouble . It also
defines a ToDouble method as an alternative to the implicit conversion operator and the ToSingle , FromDouble ,
and FromSingle methods as alternatives to the explicit conversion operators.

using System;

public struct UDouble


{
private double number;

public UDouble(double value)


{
if (value < 0)
throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

number = value;
}

public UDouble(float value)


{
if (value < 0)
throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

number = value;
}

public static readonly UDouble MinValue = (UDouble) 0.0;


public static readonly UDouble MaxValue = (UDouble) Double.MaxValue;

public static explicit operator Double(UDouble value)


{
return value.number;
return value.number;
}

public static implicit operator Single(UDouble value)


{
if (value.number > (double) Single.MaxValue)
throw new InvalidCastException("A UDouble value is out of range of the Single type.");

return (float) value.number;


}

public static explicit operator UDouble(double value)


{
if (value < 0)
throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

return new UDouble(value);


}

public static implicit operator UDouble(float value)


{
if (value < 0)
throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

return new UDouble(value);


}

public static Double ToDouble(UDouble value)


{
return (Double) value;
}

public static float ToSingle(UDouble value)


{
return (float) value;
}

public static UDouble FromDouble(double value)


{
return new UDouble(value);
}

public static UDouble FromSingle(float value)


{
return new UDouble(value);
}
}
Public Structure UDouble
Private number As Double

Public Sub New(value As Double)


If value < 0 Then
Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
End If
number = value
End Sub

Public Sub New(value As Single)


If value < 0 Then
Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
End If
number = value
End Sub

Public Shared ReadOnly MinValue As UDouble = CType(0.0, UDouble)


Public Shared ReadOnly MaxValue As UDouble = Double.MaxValue

Public Shared Widening Operator CType(value As UDouble) As Double


Return value.number
End Operator

Public Shared Narrowing Operator CType(value As UDouble) As Single


If value.number > CDbl(Single.MaxValue) Then
Throw New InvalidCastException("A UDouble value is out of range of the Single type.")
End If
Return CSng(value.number)
End Operator

Public Shared Narrowing Operator CType(value As Double) As UDouble


If value < 0 Then
Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
End If
Return New UDouble(value)
End Operator

Public Shared Narrowing Operator CType(value As Single) As UDouble


If value < 0 Then
Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
End If
Return New UDouble(value)
End Operator

Public Shared Function ToDouble(value As UDouble) As Double


Return CType(value, Double)
End Function

Public Shared Function ToSingle(value As UDouble) As Single


Return CType(value, Single)
End Function

Public Shared Function FromDouble(value As Double) As UDouble


Return New UDouble(value)
End Function

Public Shared Function FromSingle(value As Single) As UDouble


Return New UDouble(value)
End Function
End Structure

Arrays
CLS-compliant arrays conform to the following rules:
All dimensions of an array must have a lower bound of zero. The following example creates a non-CLS-
compliant array with a lower bound of one. Note that, despite the presence of the CLSCompliantAttribute
attribute, the compiler does not detect that the array returned by the Numbers.GetTenPrimes method is not
CLS-compliant.

[assembly: CLSCompliant(true)]

public class Numbers


{
public static Array GetTenPrimes()
{
Array arr = Array.CreateInstance(typeof(Int32), new int[] {10}, new int[] {1});
arr.SetValue(1, 1);
arr.SetValue(2, 2);
arr.SetValue(3, 3);
arr.SetValue(5, 4);
arr.SetValue(7, 5);
arr.SetValue(11, 6);
arr.SetValue(13, 7);
arr.SetValue(17, 8);
arr.SetValue(19, 9);
arr.SetValue(23, 10);

return arr;
}
}

<Assembly: CLSCompliant(True)>

Public Class Numbers


Public Shared Function GetTenPrimes() As Array
Dim arr As Array = Array.CreateInstance(GetType(Int32), {10}, {1})
arr.SetValue(1, 1)
arr.SetValue(2, 2)
arr.SetValue(3, 3)
arr.SetValue(5, 4)
arr.SetValue(7, 5)
arr.SetValue(11, 6)
arr.SetValue(13, 7)
arr.SetValue(17, 8)
arr.SetValue(19, 9)
arr.SetValue(23, 10)
Return arr
End Function
End Class

All array elements must consist of CLS-compliant types. The following example defines two methods that
return non-CLS-compliant arrays. The first returns an array of UInt32 values. The second returns an Object
array that includes Int32 and UInt32 values. Although the compiler identifies the first array as non-
compliant because of its UInt32 type, it fails to recognize that the second array includes non-CLS-compliant
elements.
using System;

[assembly: CLSCompliant(true)]

public class Numbers


{
public static UInt32[] GetTenPrimes()
{
uint[] arr = { 1u, 2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u };
return arr;
}

public static Object[] GetFivePrimes()


{
Object[] arr = { 1, 2, 3, 5u, 7u };
return arr;
}
}
// Compilation produces a compiler warning like the following:
// Array2.cs(8,27): warning CS3002: Return type of 'Numbers.GetTenPrimes()' is not
// CLS-compliant

<Assembly: CLSCompliant(True)>

Public Class Numbers


Public Shared Function GetTenPrimes() As UInt32()
Return { 1ui, 2ui, 3ui, 5ui, 7ui, 11ui, 13ui, 17ui, 19ui }
End Function
Public Shared Function GetFivePrimes() As Object()
Dim arr() As Object = { 1, 2, 3, 5ui, 7ui }
Return arr
End Function
End Class
' Compilation produces a compiler warning like the following:
' warning BC40027: Return type of function 'GetTenPrimes' is not CLS-compliant.

Overload resolution for methods that have array parameters is based on the fact that they are arrays and on
their element type. For this reason, the following definition of an overloaded GetSquares method is CLS-
compliant.
using System;
using System.Numerics;

[assembly: CLSCompliant(true)]

public class Numbers


{
public static byte[] GetSquares(byte[] numbers)
{
byte[] numbersOut = new byte[numbers.Length];
for (int ctr = 0; ctr < numbers.Length; ctr++) {
int square = ((int) numbers[ctr]) * ((int) numbers[ctr]);
if (square <= Byte.MaxValue)
numbersOut[ctr] = (byte) square;
// If there's an overflow, assign MaxValue to the corresponding
// element.
else
numbersOut[ctr] = Byte.MaxValue;

}
return numbersOut;
}

public static BigInteger[] GetSquares(BigInteger[] numbers)


{
BigInteger[] numbersOut = new BigInteger[numbers.Length];
for (int ctr = 0; ctr < numbers.Length; ctr++)
numbersOut[ctr] = numbers[ctr] * numbers[ctr];

return numbersOut;
}
}

Imports System.Numerics

<Assembly: CLSCompliant(True)>

Public Module Numbers


Public Function GetSquares(numbers As Byte()) As Byte()
Dim numbersOut(numbers.Length - 1) As Byte
For ctr As Integer = 0 To numbers.Length - 1
Dim square As Integer = (CInt(numbers(ctr)) * CInt(numbers(ctr)))
If square <= Byte.MaxValue Then
numbersOut(ctr) = CByte(square)
' If there's an overflow, assign MaxValue to the corresponding
' element.
Else
numbersOut(ctr) = Byte.MaxValue
End If
Next
Return numbersOut
End Function

Public Function GetSquares(numbers As BigInteger()) As BigInteger()


Dim numbersOut(numbers.Length - 1) As BigInteger
For ctr As Integer = 0 To numbers.Length - 1
numbersOut(ctr) = numbers(ctr) * numbers(ctr)
Next
Return numbersOut
End Function
End Module

Interfaces
CLS-compliant interfaces can define properties, events, and virtual methods (methods with no implementation). A
CLS-compliant interface cannot have any of the following:
Static methods or static fields. The C# compiler generatse compiler errors if you define a static member in an
interface.
Fields. The C# acompiler generates compiler errors if you define a field in an interface.
Methods that are not CLS-compliant. For example, the following interface definition includes a method,
INumber.GetUnsigned , that is marked as non-CLS-compliant. This example generates a compiler warning.

using System;

[assembly:CLSCompliant(true)]

public interface INumber


{
int Length();
[CLSCompliant(false)] ulong GetUnsigned();
}
// Attempting to compile the example displays output like the following:
// Interface2.cs(8,32): warning CS3010: 'INumber.GetUnsigned()': CLS-compliant interfaces
// must have only CLS-compliant members

<Assembly: CLSCompliant(True)>

Public Interface INumber


Function Length As Integer
<CLSCompliant(False)> Function GetUnsigned As ULong
End Interface
' Attempting to compile the example displays output like the following:
' Interface2.vb(9) : warning BC40033: Non CLS-compliant 'function' is not allowed in a
' CLS-compliant interface.
'
' <CLSCompliant(False)> Function GetUnsigned As ULong
' ~~~~~~~~~~~

Because of this rule, CLS-compliant types are not required to implement non-CLS-compliant members. If a
CLS-compliant framework does expose a class that implements a non-CLS compliant interface, it should also
provide concrete implementations of all non-CLS-compliant members.
CLS-compliant language compilers must also allow a class to provide separate implementations of members that
have the same name and signature in multiple interfaces. C# supports explicit interface implementations to provide
different implementations of identically named methods. The following example illustrates this scenario by defining
a Temperature class that implements the ICelsius and IFahrenheit interfaces as explicit interface
implementations.
using System;

[assembly: CLSCompliant(true)]

public interface IFahrenheit


{
decimal GetTemperature();
}

public interface ICelsius


{
decimal GetTemperature();
}

public class Temperature : ICelsius, IFahrenheit


{
private decimal _value;

public Temperature(decimal value)


{
// We assume that this is the Celsius value.
_value = value;
}

decimal IFahrenheit.GetTemperature()
{
return _value * 9 / 5 + 32;
}

decimal ICelsius.GetTemperature()
{
return _value;
}
}
public class Example
{
public static void Main()
{
Temperature temp = new Temperature(100.0m);
ICelsius cTemp = temp;
IFahrenheit fTemp = temp;
Console.WriteLine("Temperature in Celsius: {0} degrees",
cTemp.GetTemperature());
Console.WriteLine("Temperature in Fahrenheit: {0} degrees",
fTemp.GetTemperature());
}
}
// The example displays the following output:
// Temperature in Celsius: 100.0 degrees
// Temperature in Fahrenheit: 212.0 degrees
Assembly: CLSCompliant(True)>

Public Interface IFahrenheit


Function GetTemperature() As Decimal
End Interface

Public Interface ICelsius


Function GetTemperature() As Decimal
End Interface

Public Class Temperature : Implements ICelsius, IFahrenheit


Private _value As Decimal

Public Sub New(value As Decimal)


' We assume that this is the Celsius value.
_value = value
End Sub

Public Function GetFahrenheit() As Decimal _


Implements IFahrenheit.GetTemperature
Return _value * 9 / 5 + 32
End Function

Public Function GetCelsius() As Decimal _


Implements ICelsius.GetTemperature
Return _value
End Function
End Class

Module Example
Public Sub Main()
Dim temp As New Temperature(100.0d)
Console.WriteLine("Temperature in Celsius: {0} degrees",
temp.GetCelsius())
Console.WriteLine("Temperature in Fahrenheit: {0} degrees",
temp.GetFahrenheit())
End Sub
End Module
' The example displays the following output:
' Temperature in Celsius: 100.0 degrees
' Temperature in Fahrenheit: 212.0 degrees

Enumerations
CLS-compliant enumerations must follow these rules:
The underlying type of the enumeration must be an intrinsic CLS-compliant integer (Byte, Int16, Int32, or
Int64). For example, the following code tries to define an enumeration whose underlying type is UInt32 and
generates a compiler warning.
using System;

[assembly: CLSCompliant(true)]

public enum Size : uint {


Unspecified = 0,
XSmall = 1,
Small = 2,
Medium = 3,
Large = 4,
XLarge = 5
};

public class Clothing


{
public string Name;
public string Type;
public string Size;
}
// The attempt to compile the example displays a compiler warning like the following:
// Enum3.cs(6,13): warning CS3009: 'Size': base type 'uint' is not CLS-compliant

<Assembly: CLSCompliant(True)>

Public Enum Size As UInt32


Unspecified = 0
XSmall = 1
Small = 2
Medium = 3
Large = 4
XLarge = 5
End Enum

Public Class Clothing


Public Name As String
Public Type As String
Public Size As Size
End Class
' The attempt to compile the example displays a compiler warning like the following:
' Enum3.vb(6) : warning BC40032: Underlying type 'UInt32' of Enum is not CLS-compliant.
'
' Public Enum Size As UInt32
' ~~~~

An enumeration type must have a single instance field named Value__ that is marked with the
FieldAttributes.RTSpecialName attribute. This enables you to reference the field value implicitly.

An enumeration includes literal static fields whose types match the type of the enumeration itself. For
example, if you define a State enumeration with values of State.On and State.Off , State.On and
State.Off are both literal static fields whose type is State .

There are two kinds of enumerations:


An enumeration that represents a set of mutually exclusive, named integer values. This type of
enumeration is indicated by the absence of the System.FlagsAttribute custom attribute.
An enumeration that represents a set of bit flags that can combine to generate an unnamed value.
This type of enumeration is indicated by the presence of the System.FlagsAttribute custom attribute.
For more information, see the documentation for the Enum structure.
The value of an enumeration is not limited to the range of its specified values. In other words, the range of
values in an enumeration is the range of its underlying value. You can use the Enum.IsDefined method to
determine whether a specified value is a member of an enumeration.
Type members in general
The Common Language Specification requires all fields and methods to be accessed as members of a particular
class. Therefore, global static fields and methods (that is, static fields or methods that are defined apart from a type)
are not CLS-compliant. If you try to include a global field or method in your source code, the C# compiler generates
a compiler error.
The Common Language Specification supports only the standard managed calling convention. It doesn't support
unmanaged calling conventions and methods with variable argument lists marked with the varargs keyword. For
variable argument lists that are compatible with the standard managed calling convention, use the
ParamArrayAttribute attribute or the individual language's implementation, such as the params keyword in C# and
the ParamArray keyword in Visual Basic.
Member accessibility
Overriding an inherited member cannot change the accessibility of that member. For example, a public method in a
base class cannot be overridden by a private method in a derived class. There is one exception: a
protected internal (in C#) or Protected Friend (in Visual Basic) member in one assembly that is overridden by a
type in a different assembly. In that case, the accessibility of the override is Protected .
The following example illustrates the error that is generated when the CLSCompliantAttribute attribute is set to
true , and Person , which is a class derived from Animal , tries to change the accessibility of the Species property
from public to private. The example compiles successfully if its accessibility is changed to public.
using System;

[assembly: CLSCompliant(true)]

public class Animal


{
private string _species;

public Animal(string species)


{
_species = species;
}

public virtual string Species


{
get { return _species; }
}

public override string ToString()


{
return _species;
}
}

public class Human : Animal


{
private string _name;

public Human(string name) : base("Homo Sapiens")


{
_name = name;
}

public string Name


{
get { return _name; }
}

private override string Species


{
get { return base.Species; }
}

public override string ToString()


{
return _name;
}
}

public class Example


{
public static void Main()
{
Human p = new Human("John");
Console.WriteLine(p.Species);
Console.WriteLine(p.ToString());
}
}
// The example displays the following output:
// error CS0621: 'Human.Species': virtual or abstract members cannot be private
<Assembly: CLSCompliant(True)>

Public Class Animal


Private _species As String

Public Sub New(species As String)


_species = species
End Sub

Public Overridable ReadOnly Property Species As String


Get
Return _species
End Get
End Property

Public Overrides Function ToString() As String


Return _species
End Function
End Class

Public Class Human : Inherits Animal


Private _name As String

Public Sub New(name As String)


MyBase.New("Homo Sapiens")
_name = name
End Sub

Public ReadOnly Property Name As String


Get
Return _name
End Get
End Property

Private Overrides ReadOnly Property Species As String


Get
Return MyBase.Species
End Get
End Property

Public Overrides Function ToString() As String


Return _name
End Function
End Class

Public Module Example


Public Sub Main()
Dim p As New Human("John")
Console.WriteLine(p.Species)
Console.WriteLine(p.ToString())
End Sub
End Module
' The example displays the following output:
' 'Private Overrides ReadOnly Property Species As String' cannot override
' 'Public Overridable ReadOnly Property Species As String' because
' they have different access levels.
'
' Private Overrides ReadOnly Property Species As String

Types in the signature of a member must be accessible whenever that member is accessible. For example, this
means that a public member cannot include a parameter whose type is private, protected, or internal. The following
example illustrates the compiler error that results when a StringWrapper class constructor exposes an internal
StringOperationType enumeration value that determines how a string value should be wrapped.
using System;
using System.Text;

public class StringWrapper


{
string internalString;
StringBuilder internalSB = null;
bool useSB = false;

public StringWrapper(StringOperationType type)


{
if (type == StringOperationType.Normal) {
useSB = false;
}
else {
useSB = true;
internalSB = new StringBuilder();
}
}

// The remaining source code...


}

internal enum StringOperationType { Normal, Dynamic }


// The attempt to compile the example displays the following output:
// error CS0051: Inconsistent accessibility: parameter type
// 'StringOperationType' is less accessible than method
// 'StringWrapper.StringWrapper(StringOperationType)'

Imports System.Text

<Assembly:CLSCompliant(True)>

Public Class StringWrapper

Dim internalString As String


Dim internalSB As StringBuilder = Nothing
Dim useSB As Boolean = False

Public Sub New(type As StringOperationType)


If type = StringOperationType.Normal Then
useSB = False
Else
internalSB = New StringBuilder()
useSB = True
End If
End Sub

' The remaining source code...


End Class

Friend Enum StringOperationType As Integer


Normal = 0
Dynamic = 1
End Enum
' The attempt to compile the example displays the following output:
' error BC30909: 'type' cannot expose type 'StringOperationType'
' outside the project through class 'StringWrapper'.
'
' Public Sub New(type As StringOperationType)
' ~~~~~~~~~~~~~~~~~~~

Generic types and members


Nested types always have at least as many generic parameters as their enclosing type. These correspond by
position to the generic parameters in the enclosing type. The generic type can also include new generic parameters.
The relationship between the generic type parameters of a containing type and its nested types may be hidden by
the syntax of individual languages. In the following example, a generic type Outer<T> contains two nested classes,
Inner1A and Inner1B<U> . The calls to the ToString method, which each class inherits from Object.ToString , show
that each nested class includes the type parameters of its containing class.

using System;

[assembly:CLSCompliant(true)]

public class Outer<T>


{
T value;

public Outer(T value)


{
this.value = value;
}

public class Inner1A : Outer<T>


{
public Inner1A(T value) : base(value)
{ }
}

public class Inner1B<U> : Outer<T>


{
U value2;

public Inner1B(T value1, U value2) : base(value1)


{
this.value2 = value2;
}
}
}

public class Example


{
public static void Main()
{
var inst1 = new Outer<String>("This");
Console.WriteLine(inst1);

var inst2 = new Outer<String>.Inner1A("Another");


Console.WriteLine(inst2);

var inst3 = new Outer<String>.Inner1B<int>("That", 2);


Console.WriteLine(inst3);
}
}
// The example displays the following output:
// Outer`1[System.String]
// Outer`1+Inner1A[System.String]
// Outer`1+Inner1B`1[System.String,System.Int32]
<Assembly:CLSCompliant(True)>

Public Class Outer(Of T)


Dim value As T

Public Sub New(value As T)


Me.value = value
End Sub

Public Class Inner1A : Inherits Outer(Of T)


Public Sub New(value As T)
MyBase.New(value)
End Sub
End Class

Public Class Inner1B(Of U) : Inherits Outer(Of T)


Dim value2 As U

Public Sub New(value1 As T, value2 As U)


MyBase.New(value1)
Me.value2 = value2
End Sub
End Class
End Class

Public Module Example


Public Sub Main()
Dim inst1 As New Outer(Of String)("This")
Console.WriteLine(inst1)

Dim inst2 As New Outer(Of String).Inner1A("Another")


Console.WriteLine(inst2)

Dim inst3 As New Outer(Of String).Inner1B(Of Integer)("That", 2)


Console.WriteLine(inst3)
End Sub
End Module
' The example displays the following output:
' Outer`1[System.String]
' Outer`1+Inner1A[System.String]
' Outer`1+Inner1B`1[System.String,System.Int32]

Generic type names are encoded in the form name'n, where name is the type name, ` is a character literal, and n is
the number of parameters declared on the type, or, for nested generic types, the number of newly introduced type
parameters. This encoding of generic type names is primarily of interest to developers who use reflection to access
CLS-complaint generic types in a library.
If constraints are applied to a generic type, any types used as constraints must also be CLS-compliant. The following
example defines a class named BaseClass that is not CLS-compliant and a generic class named BaseCollection
whose type parameter must derive from BaseClass . But because BaseClass is not CLS-compliant, the compiler
emits a warning.
using System;

[assembly:CLSCompliant(true)]

[CLSCompliant(false)] public class BaseClass


{}

public class BaseCollection<T> where T : BaseClass


{}
// Attempting to compile the example displays the following output:
// warning CS3024: Constraint type 'BaseClass' is not CLS-compliant

Assembly: CLSCompliant(True)>

<CLSCompliant(False)> Public Class BaseClass


End Class

Public Class BaseCollection(Of T As BaseClass)


End Class
' Attempting to compile the example displays the following output:
' warning BC40040: Generic parameter constraint type 'BaseClass' is not
' CLS-compliant.
'
' Public Class BaseCollection(Of T As BaseClass)
' ~~~~~~~~~

If a generic type is derived from a generic base type, it must redeclare any constraints so that it can guarantee that
constraints on the base type are also satisfied. The following example defines a Number<T> that can represent any
numeric type. It also defines a FloatingPoint<T> class that represents a floating point value. However, the source
code fails to compile, because it does not apply the constraint on Number<T> (that T must be a value type) to
FloatingPoint<T> .
using System;

[assembly:CLSCompliant(true)]

public class Number<T> where T : struct


{
// use Double as the underlying type, since its range is a superset of
// the ranges of all numeric types except BigInteger.
protected double number;

public Number(T value)


{
try {
this.number = Convert.ToDouble(value);
}
catch (OverflowException e) {
throw new ArgumentException("value is too large.", e);
}
catch (InvalidCastException e) {
throw new ArgumentException("The value parameter is not numeric.", e);
}
}

public T Add(T value)


{
return (T) Convert.ChangeType(number + Convert.ToDouble(value), typeof(T));
}

public T Subtract(T value)


{
return (T) Convert.ChangeType(number - Convert.ToDouble(value), typeof(T));
}
}

public class FloatingPoint<T> : Number<T>


{
public FloatingPoint(T number) : base(number)
{
if (typeof(float) == number.GetType() ||
typeof(double) == number.GetType() ||
typeof(decimal) == number.GetType())
this.number = Convert.ToDouble(number);
else
throw new ArgumentException("The number parameter is not a floating-point number.");
}
}
// The attempt to comple the example displays the following output:
// error CS0453: The type 'T' must be a non-nullable value type in
// order to use it as parameter 'T' in the generic type or method 'Number<T>'
<Assembly:CLSCompliant(True)>

Public Class Number(Of T As Structure)


' Use Double as the underlying type, since its range is a superset of
' the ranges of all numeric types except BigInteger.
Protected number As Double

Public Sub New(value As T)


Try
Me.number = Convert.ToDouble(value)
Catch e As OverflowException
Throw New ArgumentException("value is too large.", e)
Catch e As InvalidCastException
Throw New ArgumentException("The value parameter is not numeric.", e)
End Try
End Sub

Public Function Add(value As T) As T


Return CType(Convert.ChangeType(number + Convert.ToDouble(value), GetType(T)), T)
End Function

Public Function Subtract(value As T) As T


Return CType(Convert.ChangeType(number - Convert.ToDouble(value), GetType(T)), T)
End Function
End Class

Public Class FloatingPoint(Of T) : Inherits Number(Of T)


Public Sub New(number As T)
MyBase.New(number)
If TypeOf number Is Single Or
TypeOf number Is Double Or
TypeOf number Is Decimal Then
Me.number = Convert.ToDouble(number)
Else
throw new ArgumentException("The number parameter is not a floating-point number.")
End If
End Sub
End Class
' The attempt to comple the example displays the following output:
' error BC32105: Type argument 'T' does not satisfy the 'Structure'
' constraint for type parameter 'T'.
'
' Public Class FloatingPoint(Of T) : Inherits Number(Of T)
' ~

The example compiles successfully if the constraint is added to the FloatingPoint<T> class.
using System;

[assembly:CLSCompliant(true)]

public class Number<T> where T : struct


{
// use Double as the underlying type, since its range is a superset of
// the ranges of all numeric types except BigInteger.
protected double number;

public Number(T value)


{
try {
this.number = Convert.ToDouble(value);
}
catch (OverflowException e) {
throw new ArgumentException("value is too large.", e);
}
catch (InvalidCastException e) {
throw new ArgumentException("The value parameter is not numeric.", e);
}
}

public T Add(T value)


{
return (T) Convert.ChangeType(number + Convert.ToDouble(value), typeof(T));
}

public T Subtract(T value)


{
return (T) Convert.ChangeType(number - Convert.ToDouble(value), typeof(T));
}
}

public class FloatingPoint<T> : Number<T> where T : struct


{
public FloatingPoint(T number) : base(number)
{
if (typeof(float) == number.GetType() ||
typeof(double) == number.GetType() ||
typeof(decimal) == number.GetType())
this.number = Convert.ToDouble(number);
else
throw new ArgumentException("The number parameter is not a floating-point number.");
}
}
<Assembly:CLSCompliant(True)>

Public Class Number(Of T As Structure)


' Use Double as the underlying type, since its range is a superset of
' the ranges of all numeric types except BigInteger.
Protected number As Double

Public Sub New(value As T)


Try
Me.number = Convert.ToDouble(value)
Catch e As OverflowException
Throw New ArgumentException("value is too large.", e)
Catch e As InvalidCastException
Throw New ArgumentException("The value parameter is not numeric.", e)
End Try
End Sub

Public Function Add(value As T) As T


Return CType(Convert.ChangeType(number + Convert.ToDouble(value), GetType(T)), T)
End Function

Public Function Subtract(value As T) As T


Return CType(Convert.ChangeType(number - Convert.ToDouble(value), GetType(T)), T)
End Function
End Class

Public Class FloatingPoint(Of T As Structure) : Inherits Number(Of T)


Public Sub New(number As T)
MyBase.New(number)
If TypeOf number Is Single Or
TypeOf number Is Double Or
TypeOf number Is Decimal Then
Me.number = Convert.ToDouble(number)
Else
throw new ArgumentException("The number parameter is not a floating-point number.")
End If
End Sub
End Class

The Common Language Specification imposes a conservative per-instantiation model for nested types and
protected members. Open generic types cannot expose fields or members with signatures that contain a specific
instantiation of a nested, protected generic type. Non-generic types that extend a specific instantiation of a generic
base class or interface cannot expose fields or members with signatures that contain a different instantiation of a
nested, protected generic type.
The following example defines a generic type, C1<T> , and a protected class, C1<T>.N . C1<T> has two methods, M1
and M2 . However, M1 is not CLS-compliant because it tries to return a C1<int>.N object from C1<T> . A second
class, C2 , is derived from C1<long> . It has two methods, M3 and M4 . M3 is not CLS-compliant because it tries to
return a C1<int>.N object from a subclass of C1<long> . Note that language compilers can be even more restrictive.
In this example, Visual Basic displays an error when it tries to compile M4 .
using System;

[assembly:CLSCompliant(true)]

public class C1<T>


{
protected class N { }

protected void M1(C1<int>.N n) { } // Not CLS-compliant - C1<int>.N not


// accessible from within C1<T> in all
// languages
protected void M2(C1<T>.N n) { } // CLS-compliant – C1<T>.N accessible
// inside C1<T>
}

public class C2 : C1<long>


{
protected void M3(C1<int>.N n) { } // Not CLS-compliant – C1<int>.N is not
// accessible in C2 (extends C1<long>)

protected void M4(C1<long>.N n) { } // CLS-compliant, C1<long>.N is


// accessible in C2 (extends C1<long>)
}
// Attempting to compile the example displays output like the following:
// Generics4.cs(9,22): warning CS3001: Argument type 'C1<int>.N' is not CLS-compliant
// Generics4.cs(18,22): warning CS3001: Argument type 'C1<int>.N' is not CLS-compliant
<Assembly:CLSCompliant(True)>

Public Class C1(Of T)


Protected Class N
End Class

Protected Sub M1(n As C1(Of Integer).N) ' Not CLS-compliant - C1<int>.N not
' accessible from within C1(Of T) in all
End Sub ' languages

Protected Sub M2(n As C1(Of T).N) ' CLS-compliant – C1(Of T).N accessible
End Sub ' inside C1(Of T)
End Class

Public Class C2 : Inherits C1(Of Long)


Protected Sub M3(n As C1(Of Integer).N) ' Not CLS-compliant – C1(Of Integer).N is not
End Sub ' accessible in C2 (extends C1(Of Long))

Protected Sub M4(n As C1(Of Long).N)


End Sub
End Class
' Attempting to compile the example displays output like the following:
' error BC30508: 'n' cannot expose type 'C1(Of Integer).N' in namespace
' '<Default>' through class 'C1'.
'
' Protected Sub M1(n As C1(Of Integer).N) ' Not CLS-compliant - C1<int>.N not
' ~~~~~~~~~~~~~~~~
' error BC30389: 'C1(Of T).N' is not accessible in this context because
' it is 'Protected'.
'
' Protected Sub M3(n As C1(Of Integer).N) ' Not CLS-compliant - C1(Of Integer).N is not
'
' ~~~~~~~~~~~~~~~~
'
' error BC30389: 'C1(Of T).N' is not accessible in this context because it is 'Protected'.
'
' Protected Sub M4(n As C1(Of Long).N)
' ~~~~~~~~~~~~~

Constructors
Constructors in CLS-compliant classes and structures must follow these rules:
A constructor of a derived class must call the instance constructor of its base class before it accesses
inherited instance data. This requirement is due to the fact that base class constructors are not inherited by
their derived classes. This rule does not apply to structures, which do not support direct inheritance.
Typically, compilers enforce this rule independently of CLS compliance, as the following example shows. It
creates a Doctor class that is derived from a Person class, but the Doctor class fails to call the Person
class constructor to initialize inherited instance fields.
using System;

[assembly: CLSCompliant(true)]

public class Person


{
private string fName, lName, _id;

public Person(string firstName, string lastName, string id)


{
if (String.IsNullOrEmpty(firstName + lastName))
throw new ArgumentNullException("Either a first name or a last name must be provided.");

fName = firstName;
lName = lastName;
_id = id;
}

public string FirstName


{
get { return fName; }
}

public string LastName


{
get { return lName; }
}

public string Id
{
get { return _id; }
}

public override string ToString()


{
return String.Format("{0}{1}{2}", fName,
String.IsNullOrEmpty(fName) ? "" : " ",
lName);
}
}

public class Doctor : Person


{
public Doctor(string firstName, string lastName, string id)
{
}

public override string ToString()


{
return "Dr. " + base.ToString();
}
}
// Attempting to compile the example displays output like the following:
// ctor1.cs(45,11): error CS1729: 'Person' does not contain a constructor that takes 0
// arguments
// ctor1.cs(10,11): (Location of symbol related to previous error)
<Assembly: CLSCompliant(True)>

Public Class Person


Private fName, lName, _id As String

Public Sub New(firstName As String, lastName As String, id As String)


If String.IsNullOrEmpty(firstName + lastName) Then
Throw New ArgumentNullException("Either a first name or a last name must be provided.")
End If

fName = firstName
lName = lastName
_id = id
End Sub

Public ReadOnly Property FirstName As String


Get
Return fName
End Get
End Property

Public ReadOnly Property LastName As String


Get
Return lName
End Get
End Property

Public ReadOnly Property Id As String


Get
Return _id
End Get
End Property

Public Overrides Function ToString() As String


Return String.Format("{0}{1}{2}", fName,
If(String.IsNullOrEmpty(fName), "", " "),
lName)
End Function
End Class

Public Class Doctor : Inherits Person


Public Sub New(firstName As String, lastName As String, id As String)
End Sub

Public Overrides Function ToString() As String


Return "Dr. " + MyBase.ToString()
End Function
End Class
' Attempting to compile the example displays output like the following:
' Ctor1.vb(46) : error BC30148: First statement of this 'Sub New' must be a call
' to 'MyBase.New' or 'MyClass.New' because base class 'Person' of 'Doctor' does
' not have an accessible 'Sub New' that can be called with no arguments.
'
' Public Sub New()
' ~~~

An object constructor cannot be called except to create an object. In addition, an object cannot be initialized
twice. For example, this means that Object.MemberwiseClone must not call constructors.
Properties
Properties in CLS-compliant types must follow these rules:
A property must have a setter, a getter, or both. In an assembly, these are implemented as special methods,
which means that they will appear as separate methods (the getter is named get _propertyname and the
setter is set*\_*propertyname*) marked as SpecialName` in the assembly's metadata. The C# compiler
enforces this rule automatically without the need to apply the CLSCompliantAttribute attribute.
A property's type is the return type of the property getter and the last argument of the setter. These types
must be CLS compliant, and arguments cannot be assigned to the property by reference (that is, they cannot
be managed pointers).
If a property has both a getter and a setter, they must both be virtual, both static, or both instance. The C#
compiler automatically enforces this rule through property definition syntax.
Events
An event is defined by its name and its type. The event type is a delegate that is used to indicate the event. For
example, the DbConnection.StateChange event is of type StateChangeEventHandler . In addition to the event itself,
three methods with names based on the event name provide the event's implementation and are marked as
SpecialName in the assembly's metadata:

A method for adding an event handler, named add _EventName. For example, the event subscription
method for the DbConnection.StateChange event is named add_StateChange .
A method for removing an event handler, named remove _EventName. For example, the removal method for
the DbConnection.StateChange event is named remove_StateChange .
A method for indicating that the event has occurred, named raise _EventName.

NOTE
Most of the Common Language Specification's rules regarding events are implemented by language compilers and are
transparent to component developers.

The methods for adding, removing, and raising the event must have the same accessibility. They must also all be
static, instance, or virtual. The methods for adding and removing an event have one parameter whose type is the
event delegate type. The add and remove methods must both be present or both be absent.
The following example defines a CLS-compliant class named Temperature that raises a TemperatureChanged event if
the change in temperature between two readings equals or exceeds a threshold value. The Temperature class
explicitly defines a raise_TemperatureChanged method so that it can selectively execute event handlers.

using System;
using System.Collections;
using System.Collections.Generic;

[assembly: CLSCompliant(true)]

public class TemperatureChangedEventArgs : EventArgs


{
private Decimal originalTemp;
private Decimal newTemp;
private DateTimeOffset when;

public TemperatureChangedEventArgs(Decimal original, Decimal @new, DateTimeOffset time)


{
originalTemp = original;
newTemp = @new;
when = time;
}

public Decimal OldTemperature


{
get { return originalTemp; }
}
public Decimal CurrentTemperature
{
get { return newTemp; }
}

public DateTimeOffset Time


{
get { return when; }
}
}

public delegate void TemperatureChanged(Object sender, TemperatureChangedEventArgs e);

public class Temperature


{
private struct TemperatureInfo
{
public Decimal Temperature;
public DateTimeOffset Recorded;
}

public event TemperatureChanged TemperatureChanged;

private Decimal previous;


private Decimal current;
private Decimal tolerance;
private List<TemperatureInfo> tis = new List<TemperatureInfo>();

public Temperature(Decimal temperature, Decimal tolerance)


{
current = temperature;
TemperatureInfo ti = new TemperatureInfo();
ti.Temperature = temperature;
tis.Add(ti);
ti.Recorded = DateTimeOffset.UtcNow;
this.tolerance = tolerance;
}

public Decimal CurrentTemperature


{
get { return current; }
set {
TemperatureInfo ti = new TemperatureInfo();
ti.Temperature = value;
ti.Recorded = DateTimeOffset.UtcNow;
previous = current;
current = value;
if (Math.Abs(current - previous) >= tolerance)
raise_TemperatureChanged(new TemperatureChangedEventArgs(previous, current, ti.Recorded));
}
}

public void raise_TemperatureChanged(TemperatureChangedEventArgs eventArgs)


{
if (TemperatureChanged == null)
return;

foreach (TemperatureChanged d in TemperatureChanged.GetInvocationList()) {


if (d.Method.Name.Contains("Duplicate"))
Console.WriteLine("Duplicate event handler; event handler not executed.");
else
d.Invoke(this, eventArgs);
}
}
}

public class Example


{
public Temperature temp;
public static void Main()
{
Example ex = new Example();
}

public Example()
{
temp = new Temperature(65, 3);
temp.TemperatureChanged += this.TemperatureNotification;
RecordTemperatures();
Example ex = new Example(temp);
ex.RecordTemperatures();
}

public Example(Temperature t)
{
temp = t;
RecordTemperatures();
}

public void RecordTemperatures()


{
temp.TemperatureChanged += this.DuplicateTemperatureNotification;
temp.CurrentTemperature = 66;
temp.CurrentTemperature = 63;
}

internal void TemperatureNotification(Object sender, TemperatureChangedEventArgs e)


{
Console.WriteLine("Notification 1: The temperature changed from {0} to {1}", e.OldTemperature,
e.CurrentTemperature);
}

public void DuplicateTemperatureNotification(Object sender, TemperatureChangedEventArgs e)


{
Console.WriteLine("Notification 2: The temperature changed from {0} to {1}", e.OldTemperature,
e.CurrentTemperature);
}
}

Imports System.Collections
Imports System.Collections.Generic

<Assembly: CLSCompliant(True)>

Public Class TemperatureChangedEventArgs : Inherits EventArgs


Private originalTemp As Decimal
Private newTemp As Decimal
Private [when] As DateTimeOffset

Public Sub New(original As Decimal, [new] As Decimal, [time] As DateTimeOffset)


originalTemp = original
newTemp = [new]
[when] = [time]
End Sub

Public ReadOnly Property OldTemperature As Decimal


Get
Return originalTemp
End Get
End Property

Public ReadOnly Property CurrentTemperature As Decimal


Get
Return newTemp
End Get
End Property

Public ReadOnly Property [Time] As DateTimeOffset


Get
Return [when]
End Get
End Property
End Class

Public Delegate Sub TemperatureChanged(sender As Object, e As TemperatureChangedEventArgs)

Public Class Temperature


Private Structure TemperatureInfo
Dim Temperature As Decimal
Dim Recorded As DateTimeOffset
End Structure

Public Event TemperatureChanged As TemperatureChanged

Private previous As Decimal


Private current As Decimal
Private tolerance As Decimal
Private tis As New List(Of TemperatureInfo)

Public Sub New(temperature As Decimal, tolerance As Decimal)


current = temperature
Dim ti As New TemperatureInfo()
ti.Temperature = temperature
ti.Recorded = DateTimeOffset.UtcNow
tis.Add(ti)
Me.tolerance = tolerance
End Sub

Public Property CurrentTemperature As Decimal


Get
Return current
End Get
Set
Dim ti As New TemperatureInfo
ti.Temperature = value
ti.Recorded = DateTimeOffset.UtcNow
previous = current
current = value
If Math.Abs(current - previous) >= tolerance Then
raise_TemperatureChanged(New TemperatureChangedEventArgs(previous, current, ti.Recorded))
End If
End Set
End Property

Public Sub raise_TemperatureChanged(eventArgs As TemperatureChangedEventArgs)


If TemperatureChangedEvent Is Nothing Then Exit Sub

Dim ListenerList() As System.Delegate = TemperatureChangedEvent.GetInvocationList()


For Each d As TemperatureChanged In TemperatureChangedEvent.GetInvocationList()
If d.Method.Name.Contains("Duplicate") Then
Console.WriteLine("Duplicate event handler; event handler not executed.")
Else
d.Invoke(Me, eventArgs)
End If
Next
End Sub
End Class

Public Class Example


Public WithEvents temp As Temperature

Public Shared Sub Main()


Dim ex As New Example()
End Sub
End Sub

Public Sub New()


temp = New Temperature(65, 3)
RecordTemperatures()
Dim ex As New Example(temp)
ex.RecordTemperatures()
End Sub

Public Sub New(t As Temperature)


temp = t
RecordTemperatures()
End Sub

Public Sub RecordTemperatures()


temp.CurrentTemperature = 66
temp.CurrentTemperature = 63

End Sub

Friend Shared Sub TemperatureNotification(sender As Object, e As TemperatureChangedEventArgs) _


Handles temp.TemperatureChanged
Console.WriteLine("Notification 1: The temperature changed from {0} to {1}", e.OldTemperature,
e.CurrentTemperature)
End Sub

Friend Shared Sub DuplicateTemperatureNotification(sender As Object, e As TemperatureChangedEventArgs) _


Handles temp.TemperatureChanged
Console.WriteLine("Notification 2: The temperature changed from {0} to {1}", e.OldTemperature,
e.CurrentTemperature)
End Sub
End Class

Overloads
The Common Language Specification imposes the following requirements on overloaded members:
Members can be overloaded based on the number of parameters and the type of any parameter. Calling
convention, return type, custom modifiers applied to the method or its parameter, and whether parameters
are passed by value or by reference are not considered when differentiating between overloads. For an
example, see the code for the requirement that names must be unique within a scope in the Naming
conventions section.
Only properties and methods can be overloaded. Fields and events cannot be overloaded.
Generic methods can be overloaded based on the number of their generic parameters.

NOTE
The op_Explicit and op_Implicit operators are exceptions to the rule that return value is not considered part of a
method signature for overload resolution. These two operators can be overloaded based on both their parameters and their
return value.

Exceptions
Exception objects must derive from System.Exception or from another type derived from System.Exception . The
following example illustrates the compiler error that results when a custom class named ErrorClass is used for
exception handling.
using System;

[assembly: CLSCompliant(true)]

public class ErrorClass


{
string msg;

public ErrorClass(string errorMessage)


{
msg = errorMessage;
}

public string Message


{
get { return msg; }
}
}

public static class StringUtilities


{
public static string[] SplitString(this string value, int index)
{
if (index < 0 | index > value.Length) {
ErrorClass badIndex = new ErrorClass("The index is not within the string.");
throw badIndex;
}
string[] retVal = { value.Substring(0, index - 1),
value.Substring(index) };
return retVal;
}
}
// Compilation produces a compiler error like the following:
// Exceptions1.cs(26,16): error CS0155: The type caught or thrown must be derived from
// System.Exception
Imports System.Runtime.CompilerServices

<Assembly: CLSCompliant(True)>

Public Class ErrorClass


Dim msg As String

Public Sub New(errorMessage As String)


msg = errorMessage
End Sub

Public ReadOnly Property Message As String


Get
Return msg
End Get
End Property
End Class

Public Module StringUtilities


<Extension()> Public Function SplitString(value As String, index As Integer) As String()
If index < 0 Or index > value.Length Then
Dim BadIndex As New ErrorClass("The index is not within the string.")
Throw BadIndex
End If
Dim retVal() As String = { value.Substring(0, index - 1),
value.Substring(index) }
Return retVal
End Function
End Module
' Compilation produces a compiler error like the following:
' Exceptions1.vb(27) : error BC30665: 'Throw' operand must derive from 'System.Exception'.
'
' Throw BadIndex
' ~~~~~~~~~~~~~~

To correct this error, the ErrorClass class must inherit from System.Exception . In addition, the Message property
must be overridden. The following example corrects these errors to define an ErrorClass class that is CLS-
compliant.
using System;

[assembly: CLSCompliant(true)]

public class ErrorClass : Exception


{
string msg;

public ErrorClass(string errorMessage)


{
msg = errorMessage;
}

public override string Message


{
get { return msg; }
}
}

public static class StringUtilities


{
public static string[] SplitString(this string value, int index)
{
if (index < 0 | index > value.Length) {
ErrorClass badIndex = new ErrorClass("The index is not within the string.");
throw badIndex;
}
string[] retVal = { value.Substring(0, index - 1),
value.Substring(index) };
return retVal;
}
}

Imports System.Runtime.CompilerServices

<Assembly: CLSCompliant(True)>

Public Class ErrorClass : Inherits Exception


Dim msg As String

Public Sub New(errorMessage As String)


msg = errorMessage
End Sub

Public Overrides ReadOnly Property Message As String


Get
Return msg
End Get
End Property
End Class

Public Module StringUtilities


<Extension()> Public Function SplitString(value As String, index As Integer) As String()
If index < 0 Or index > value.Length Then
Dim BadIndex As New ErrorClass("The index is not within the string.")
Throw BadIndex
End If
Dim retVal() As String = { value.Substring(0, index - 1),
value.Substring(index) }
Return retVal
End Function
End Module

Attributes
In.NET Framework assemblies, custom attributes provide an extensible mechanism for storing custom attributes
and retrieving metadata about programming objects, such as assemblies, types, members, and method parameters.
Custom attributes must derive from System.Attribute or from a type derived from System.Attribute .
The following example violates this rule. It defines a NumericAttribute class that does not derive from
System.Attribute . Note that a compiler error results only when the non-CLS-compliant attribute is applied, not
when the class is defined.

using System;

[assembly: CLSCompliant(true)]

[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Struct)]
public class NumericAttribute
{
private bool _isNumeric;

public NumericAttribute(bool isNumeric)


{
_isNumeric = isNumeric;
}

public bool IsNumeric


{
get { return _isNumeric; }
}
}

[Numeric(true)] public struct UDouble


{
double Value;
}
// Compilation produces a compiler error like the following:
// Attribute1.cs(22,2): error CS0616: 'NumericAttribute' is not an attribute class
// Attribute1.cs(7,14): (Location of symbol related to previous error)

<Assembly: CLSCompliant(True)>

<AttributeUsageAttribute(AttributeTargets.Class Or AttributeTargets.Struct)> _
Public Class NumericAttribute
Private _isNumeric As Boolean

Public Sub New(isNumeric As Boolean)


_isNumeric = isNumeric
End Sub

Public ReadOnly Property IsNumeric As Boolean


Get
Return _isNumeric
End Get
End Property
End Class

<Numeric(True)> Public Structure UDouble


Dim Value As Double
End Structure
' Compilation produces a compiler error like the following:
' error BC31504: 'NumericAttribute' cannot be used as an attribute because it
' does not inherit from 'System.Attribute'.
'
' <Numeric(True)> Public Structure UDouble
' ~~~~~~~~~~~~~
The constructor or the properties of a CLS-compliant attribute can expose only the following types:
Boolean
Byte
Char
Double
Int16
Int32
Int64
Single
String
Type
Any enumeration type whose underlying type is Byte , Int16 , Int32 , or Int64 .

The following example defines a DescriptionAttribute class that derives from Attribute. The class constructor has a
parameter of type Descriptor , so the class is not CLS-compliant. Note that the C# compiler emits a warning but
compiles successfully.

using System;

[assembly:CLSCompliantAttribute(true)]

public enum DescriptorType { type, member };

public class Descriptor


{
public DescriptorType Type;
public String Description;
}

[AttributeUsage(AttributeTargets.All)]
public class DescriptionAttribute : Attribute
{
private Descriptor desc;

public DescriptionAttribute(Descriptor d)
{
desc = d;
}

public Descriptor Descriptor


{ get { return desc; } }
}
// Attempting to compile the example displays output like the following:
// warning CS3015: 'DescriptionAttribute' has no accessible
// constructors which use only CLS-compliant types
<Assembly:CLSCompliantAttribute(True)>

Public Enum DescriptorType As Integer


Type = 0
Member = 1
End Enum

Public Class Descriptor


Public Type As DescriptorType
Public Description As String
End Class

<AttributeUsage(AttributeTargets.All)> _
Public Class DescriptionAttribute : Inherits Attribute
Private desc As Descriptor

Public Sub New(d As Descriptor)


desc = d
End Sub

Public ReadOnly Property Descriptor As Descriptor


Get
Return desc
End Get
End Property
End Class

The CLSCompliantAttribute attribute


The CLSCompliantAttribute attribute is used to indicate whether a program element complies with the Common
Language Specification. The CLSCompliantAttribute.CLSCompliantAttribute(Boolean) constructor includes a single
required parameter, isCompliant, that indicates whether the program element is CLS-compliant.
At compile time, the compiler detects non-compliant elements that are presumed to be CLS-compliant and emits a
warning. The compiler does not emit warnings for types or members that are explicitly declared to be non-
compliant.
Component developers can use the CLSCompliantAttribute attribute in two ways:
To define the parts of the public interface exposed by a component that are CLS-compliant and the parts that
are not CLS-compliant. When the attribute is used to mark particular program elements as CLS-compliant,
its use guarantees that those elements are accessible from all languages and tools that target the .NET
Framework.
To ensure that the component library's public interface exposes only program elements that are CLS-
compliant. If elements are not CLS-compliant, compilers will generally issue a warning.

WARNING
In some cases, language compilers enforce CLS-compliant rules regardless of whether the CLSCompliantAttribute attribute
is used. For example, defining a *static member in an interface violates a CLS rule. However, if you define a *static
member in an interface, the C# compiler displays an error message and fails to compile the app.

The CLSCompliantAttribute attribute is marked with an AttributeUsageAttribute attribute that has a value of
AttributeTargets.All . This value allows you to apply the CLSCompliantAttribute attribute to any program element,
including assemblies, modules, types (classes, structures, enumerations, interfaces, and delegates), type members
(constructors, methods, properties, fields, and events), parameters, generic parameters, and return values. However,
in practice, you should apply the attribute only to assemblies, types, and type members. Otherwise, compilers
ignore the attribute and continue to generate compiler warnings whenever they encounter a non-compliant
parameter, generic parameter, or return value in your library's public interface.
The value of the CLSCompliantAttribute attribute is inherited by contained program elements. For example, if an
assembly is marked as CLS-compliant, its types are also CLS-compliant. If a type is marked as CLS-compliant, its
nested types and members are also CLS-compliant.
You can explicitly override the inherited compliance by applying the CLSCompliantAttribute attribute to a contained
program element. For example, you can use the CLSCompliantAttribute attribute with an isCompliant value of
false to define a non-compliant type in a compliant assembly, and you can use the attribute with an isComplian
value of true to define a compliant type in a non-compliant assembly. You can also define non-compliant
members in a compliant type. However, a non-compliant type cannot have compliant members, so you cannot use
the attribute with an isCompliant value of true to override inheritance from a non-compliant type.
When you are developing components, you should always use the CLSCompliantAttribute attribute to indicate
whether your assembly, its types, and its members are CLS-compliant.
To create CLS-compliant components:
1. Use the CLSCompliantAttribute to mark you assembly as CLS-compliant.
2. Mark any publicly exposed types in the assembly that are not CLS-compliant as non-compliant.
3. Mark any publicly exposed members in CLS-compliant types as non-compliant.
4. Provide a CLS-compliant alternative for non-CLS-compliant members.
If you've successfully marked all your non-compliant types and members, your compiler should not emit any non-
compliance warnings. However, you should indicate which members are not CLS-compliant and list their CLS-
compliant alternatives in your product documentation.
The following example uses the CLSCompliantAttribute attribute to define a CLS-compliant assembly and a type,
CharacterUtilities , that has two non-CLS-compliant members. Because both members are tagged with the
CLSCompliant(false) attribute, the compiler produces no warnings. The class also provides a CLS-compliant
alternative for both methods. Ordinarily, we would just add two overloads to the ToUTF16 method to provide CLS-
compliant alternatives. However, because methods cannot be overloaded based on return value, the names of the
CLS-compliant methods are different from the names of the non-compliant methods.
using System;
using System.Text;

[assembly:CLSCompliant(true)]

public class CharacterUtilities


{
[CLSCompliant(false)] public static ushort ToUTF16(String s)
{
s = s.Normalize(NormalizationForm.FormC);
return Convert.ToUInt16(s[0]);
}

[CLSCompliant(false)] public static ushort ToUTF16(Char ch)


{
return Convert.ToUInt16(ch);
}

// CLS-compliant alternative for ToUTF16(String).


public static int ToUTF16CodeUnit(String s)
{
s = s.Normalize(NormalizationForm.FormC);
return (int) Convert.ToUInt16(s[0]);
}

// CLS-compliant alternative for ToUTF16(Char).


public static int ToUTF16CodeUnit(Char ch)
{
return Convert.ToInt32(ch);
}

public bool HasMultipleRepresentations(String s)


{
String s1 = s.Normalize(NormalizationForm.FormC);
return s.Equals(s1);
}

public int GetUnicodeCodePoint(Char ch)


{
if (Char.IsSurrogate(ch))
throw new ArgumentException("ch cannot be a high or low surrogate.");

return Char.ConvertToUtf32(ch.ToString(), 0);


}

public int GetUnicodeCodePoint(Char[] chars)


{
if (chars.Length > 2)
throw new ArgumentException("The array has too many characters.");

if (chars.Length == 2) {
if (! Char.IsSurrogatePair(chars[0], chars[1]))
throw new ArgumentException("The array must contain a low and a high surrogate.");
else
return Char.ConvertToUtf32(chars[0], chars[1]);
}
else {
return Char.ConvertToUtf32(chars.ToString(), 0);
}
}
}
Imports System.Text

<Assembly:CLSCompliant(True)>

Public Class CharacterUtilities


<CLSCompliant(False)> Public Shared Function ToUTF16(s As String) As UShort
s = s.Normalize(NormalizationForm.FormC)
Return Convert.ToUInt16(s(0))
End Function

<CLSCompliant(False)> Public Shared Function ToUTF16(ch As Char) As UShort


Return Convert.ToUInt16(ch)
End Function

' CLS-compliant alternative for ToUTF16(String).


Public Shared Function ToUTF16CodeUnit(s As String) As Integer
s = s.Normalize(NormalizationForm.FormC)
Return CInt(Convert.ToInt16(s(0)))
End Function

' CLS-compliant alternative for ToUTF16(Char).


Public Shared Function ToUTF16CodeUnit(ch As Char) As Integer
Return Convert.ToInt32(ch)
End Function

Public Function HasMultipleRepresentations(s As String) As Boolean


Dim s1 As String = s.Normalize(NormalizationForm.FormC)
Return s.Equals(s1)
End Function

Public Function GetUnicodeCodePoint(ch As Char) As Integer


If Char.IsSurrogate(ch) Then
Throw New ArgumentException("ch cannot be a high or low surrogate.")
End If
Return Char.ConvertToUtf32(ch.ToString(), 0)
End Function

Public Function GetUnicodeCodePoint(chars() As Char) As Integer


If chars.Length > 2 Then
Throw New ArgumentException("The array has too many characters.")
End If
If chars.Length = 2 Then
If Not Char.IsSurrogatePair(chars(0), chars(1)) Then
Throw New ArgumentException("The array must contain a low and a high surrogate.")
Else
Return Char.ConvertToUtf32(chars(0), chars(1))
End If
Else
Return Char.ConvertToUtf32(chars.ToString(), 0)
End If
End Function
End Class

If you are developing an app rather than a library (that is, if you aren't exposing types or members that can be
consumed by other app developers), the CLS compliance of the program elements that your app consumes are of
interest only if your language does not support them. In that case, your language compiler will generate an error
when you try to use a non-CLS-compliant element.

Cross-Language Interoperability
Language independence has a number of possible meanings. One meaning involves seamlessly consuming types
written in one language from an app written in another language. A second meaning, which is the focus of this
article, involves combining code written in multiple languages into a single .NET Framework assembly.
The following example illustrates cross-language interoperability by creating a class library named Utilities.dll that
includes two classes, NumericLib and StringLib . The NumericLib class is written in C#, and the StringLib class is
written in Visual Basic. Here's the source code for StringUtil.vb , which includes a single member, ToTitleCase , in
its StringLib class.

Imports System.Collections.Generic
Imports System.Runtime.CompilerServices

Public Module StringLib


Private exclusions As List(Of String)

Sub New()
Dim words() As String = { "a", "an", "and", "of", "the" }
exclusions = New List(Of String)
exclusions.AddRange(words)
End Sub

<Extension()> _
Public Function ToTitleCase(title As String) As String
Dim words() As String = title.Split()
Dim result As String = String.Empty

For ctr As Integer = 0 To words.Length - 1


Dim word As String = words(ctr)
If ctr = 0 OrElse Not exclusions.Contains(word.ToLower()) Then
result += word.Substring(0, 1).ToUpper() + _
word.Substring(1).ToLower()
Else
result += word.ToLower()
End If
If ctr <= words.Length - 1 Then
result += " "
End If
Next
Return result
End Function
End Module

Here's the source code for NumberUtil.cs, which defines a NumericLib class that has two members, IsEven and
NearZero .
using System;

public static class NumericLib


{
public static bool IsEven(this IConvertible number)
{
if (number is Byte ||
number is SByte ||
number is Int16 ||
number is UInt16 ||
number is Int32 ||
number is UInt32 ||
number is Int64)
return ((long) number) % 2 == 0;
else if (number is UInt64)
return ((ulong) number) %2 == 0;
else
throw new NotSupportedException("IsEven called for a non-integer value.");
}

public static bool NearZero(double number)


{
return number < .00001;
}
}

To package the two classes in a single assembly, you must compile them into modules. To compile the Visual Basic
source code file into a module, use this command:

vbc /t:module StringUtil.vb

To compile the C# source code file into a module, use this command:

csc /t:module NumberUtil.cs

You then use the Link tool (Link.exe) to compile the two modules into an assembly:

link numberutil.netmodule stringutil.netmodule /out:UtilityLib.dll /dll

The following example then calls the NumericLib.NearZero and StringLib.ToTitleCase methods. Note that both the
Visual Basic code and the C# code are able to access the methods in both classes.

using System;

public class Example


{
public static void Main()
{
Double dbl = 0.0 - Double.Epsilon;
Console.WriteLine(NumericLib.NearZero(dbl));

string s = "war and peace";


Console.WriteLine(s.ToTitleCase());
}
}
// The example displays the following output:
// True
// War and Peace
Module Example
Public Sub Main()
Dim dbl As Double = 0.0 - Double.Epsilon
Console.WriteLine(NumericLib.NearZero(dbl))

Dim s As String = "war and peace"


Console.WriteLine(s.ToTitleCase())
End Sub
End Module
' The example displays the following output:
' True
' War and Peace

To compile the Visual Basic code, use this command:

vbc example.vb /r:UtilityLib.dll

To compile with C#, change the name of the compiler from vbc to csc, and change the file extension from .vb to .cs:

csc example.cs /r:UtilityLib.dll


Language Independence and Language-Independent
Components
7/29/2017 • 68 min to read • Edit Online

The .NET Framework is language independent. This means that, as a developer, you can develop in one of the
many languages that target the .NET Framework, such as C#, C++/CLI, Eiffel, F#, IronPython, IronRuby,
PowerBuilder, Visual Basic, Visual COBOL, and Windows PowerShell. You can access the types and members of
class libraries developed for the .NET Framework without having to know the language in which they were
originally written and without having to follow any of the original language's conventions. If you are a component
developer, your component can be accessed by any .NET Framework app regardless of its language.

NOTE
This first part of this article discusses creating language-independent components—that is, components that can be
consumed by apps that are written in any language. You can also create a single component or app from source code
written in multiple languages; see Cross-Language Interoperability in the second part of this article.

To fully interact with other objects written in any language, objects must expose to callers only those features that
are common to all languages. This common set of features is defined by the Common Language Specification
(CLS), which is a set of rules that apply to generated assemblies. The Common Language Specification is defined in
Partition I, Clauses 7 through 11 of the ECMA-335 Standard: Common Language Infrastructure.
If your component conforms to the Common Language Specification, it is guaranteed to be CLS-compliant and can
be accessed from code in assemblies written in any programming language that supports the CLS. You can
determine whether your component conforms to the Common Language Specification at compile time by
applying the CLSCompliantAttribute attribute to your source code. For more information, see The
CLSCompliantAttribute attribute.
In this article:
CLS compliance rules
Types and type member signatures
Naming conventions
Type conversion
Arrays
Interfaces
Enumerations
Type members in general
Member accessibility
Generic types and members
Constructors
Properties
Events
Overloads
Exceptions
Attributes
The CLSCompliantAttribute attribute
Cross-Language Interoperability

CLS compliance rules


This section discusses the rules for creating a CLS-compliant component. For a complete list of rules, see Partition
I, Clause 11 of the ECMA-335 Standard: Common Language Infrastructure.

NOTE
The Common Language Specification discusses each rule for CLS compliance as it applies to consumers (developers who are
programmatically accessing a component that is CLS-compliant), frameworks (developers who are using a language compiler
to create CLS-compliant libraries), and extenders (developers who are creating a tool such as a language compiler or a code
parser that creates CLS-compliant components). This article focuses on the rules as they apply to frameworks. Note, though,
that some of the rules that apply to extenders may also apply to assemblies that are created using Reflection.Emit.

To design a component that is language independent, you only need to apply the rules for CLS compliance to your
component's public interface. Your private implementation does not have to conform to the specification.

IMPORTANT
The rules for CLS compliance apply only to a component's public interface, not to its private implementation.

For example, unsigned integers other than Byte are not CLS-compliant. Because the Person class in the following
example exposes an Age property of type UInt16, the following code displays a compiler warning.

using System;

[assembly: CLSCompliant(true)]

public class Person


{
private UInt16 personAge = 0;

public UInt16 Age


{ get { return personAge; } }
}
// The attempt to compile the example displays the following compiler warning:
// Public1.cs(10,18): warning CS3003: Type of 'Person.Age' is not CLS-compliant
<Assembly: CLSCompliant(True)>

Public Class Person


Private personAge As UInt16

Public ReadOnly Property Age As UInt16


Get
Return personAge
End Get
End Property
End Class
' The attempt to compile the example displays the following compiler warning:
' Public1.vb(9) : warning BC40027: Return type of function 'Age' is not CLS-compliant.
'
' Public ReadOnly Property Age As UInt16
' ~~~

You can make the Person class CLS-compliant by changing the type of Age property from UInt16 to Int16, which
is a CLS-compliant, 16-bit signed integer. You do not have to change the type of the private personAge field.

using System;

[assembly: CLSCompliant(true)]

public class Person


{
private Int16 personAge = 0;

public Int16 Age


{ get { return personAge; } }
}

<Assembly: CLSCompliant(True)>

Public Class Person


Private personAge As UInt16

Public ReadOnly Property Age As Int16


Get
Return CType(personAge, Int16)
End Get
End Property
End Class

A library's public interface consists of the following:


Definitions of public classes.
Definitions of the public members of public classes, and definitions of members accessible to derived
classes (that is, protected members).
Parameters and return types of public methods of public classes, and parameters and return types of
methods accessible to derived classes.
The rules for CLS compliance are listed in the following table. The text of the rules is taken verbatim from the
ECMA-335 Standard: Common Language Infrastructure, which is Copyright 2012 by Ecma International. More
detailed information about these rules is found in the following sections.
CATEGORY SEE RULE RULE NUMBER

Accessibility Member accessibility Accessibility shall not be 10


changed when overriding
inherited methods, except
when overriding a method
inherited from a different
assembly with accessibility
family-or-assembly . In
this case, the override shall
have accessibility family .

Accessibility Member accessibility The visibility and accessibility 12


of types and members shall
be such that types in the
signature of any member
shall be visible and
accessible whenever the
member itself is visible and
accessible. For example, a
public method that is visible
outside its assembly shall
not have an argument
whose type is visible only
within the assembly. The
visibility and accessibility of
types composing an
instantiated generic type
used in the signature of any
member shall be visible and
accessible whenever the
member itself is visible and
accessible. For example, an
instantiated generic type
present in the signature of a
member that is visible
outside its assembly shall
not have a generic
argument whose type is
visible only within the
assembly.

Arrays Arrays Arrays shall have elements 16


with a CLS-compliant type,
and all dimensions of the
array shall have lower
bounds of zero. Only the
fact that an item is an array
and the element type of the
array shall be required to
distinguish between
overloads. When
overloading is based on two
or more array types the
element types shall be
named types.

Attributes Attributes Attributes shall be of type 41


System.Attribute, or a type
inheriting from it.
CATEGORY SEE RULE RULE NUMBER

Attributes Attributes The CLS only allows a subset 34


of the encodings of custom
attributes. The only types
that shall appear in these
encodings are (see Partition
IV): System.Type,
System.String, System.Char,
System.Boolean,
System.Byte, System.Int16,
System.Int32, System.Int64,
System.Single,
System.Double, and any
enumeration type based on
a CLS-compliant base
integer type.

Attributes Attributes The CLS does not allow 35


publicly visible required
modifiers ( modreq , see
Partition II), but does allow
optional modifiers ( modopt ,
see Partition II) it does not
understand.

Constructors Constructors An object constructor shall 21


call some instance
constructor of its base class
before any access occurs to
inherited instance data. (This
does not apply to value
types, which need not have
constructors.)

Constructors Constructors An object constructor shall 22


not be called except as part
of the creation of an object,
and an object shall not be
initialized twice.

Enumerations Enumerations The underlying type of an 7


enum shall be a built-in CLS
integer type, the name of
the field shall be "value__",
and that field shall be
marked RTSpecialName .

Enumerations Enumerations There are two distinct kinds 8


of enums, indicated by the
presence or absence of the
System.FlagsAttribute (see
Partition IV Library) custom
attribute. One represents
named integer values; the
other represents named bit
flags that can be combined
to generate an unnamed
value. The value of an enum
is not limited to the specified
values.
CATEGORY SEE RULE RULE NUMBER

Enumerations Enumerations Literal static fields of an 9


enum shall have the type of
the enum itself.

Events Events The methods that 29


implement an event shall be
marked SpecialName in
themetadata.

Events Events The accessibility of an event 30


and of its accessors shall be
identical.

Events Events The add and remove 31


methods for an event shall
both either be present or
absent.

Events Events The add and remove 32


methods for an event shall
each take one parameter
whose type defines the type
of the event and that shall
be derived from
System.Delegate.

Events Events Events shall adhere to a 33


specific naming pattern. The
SpecialName attribute
referred to in CLS rule 29
shall be ignored in
appropriate name
comparisons and shall
adhere to identifier rules.

Exceptions Exceptions Objects that are thrown 40


shall be of type
System.Exception or a type
inheriting from it.
Nonetheless, CLS-compliant
methods are not required to
block the propagation of
other types of exceptions.

General CLS compliance: the Rules CLS rules apply only to 1


those parts of a type that
are accessible or visible
outsideof the defining
assembly.

General CLS compliance: the Rules Members of non-CLS 2


compliant types shall not be
marked CLS-compliant.
CATEGORY SEE RULE RULE NUMBER

Generics Generic types and members Nested types shall have at 42


least as many generic
parameters as the enclosing
type. Generic parameters in
a nested type correspond by
position to the generic
parameters in its enclosing
type.

Generics Generic types and members The name of a generic type 43


shall encode the number of
type parameters declared on
the non-nested type, or
newly introduced to the
type if nested, according to
the rules defined above.

Generics Generic types and members A generic type shall 4444


redeclare sufficient
constraints to guarantee
that any constraints on the
base type, or interfaces
would be satisfied by the
generic type constraints.

Generics Generic types and members Types used as constraints on 45


generic parameters shall
themselves be CLS-
compliant.

Generics Generic types and members The visibility and accessibility 46


of members (including
nested types) in an
instantiated generic type
shall be considered to be
scoped to the specific
instantiation rather than the
generic type declaration as a
whole. Assuming this, the
visibility and accessibility
rules of CLS rule 12 still
apply.

Generics Generic types and members For each abstract or virtual 47


generic method, there shall
be a default concrete
(nonabstract)
implementation.

Interfaces Interfaces CLS-compliant interfaces 18


shall not require the
definition of non-CLS
compliantmethods in order
to implement them.
CATEGORY SEE RULE RULE NUMBER

Interfaces Interfaces CLS-compliant interfaces 19


shall not define static
methods, nor shall they
define fields.

Members Type members in general Global static fields and 36


methods are not CLS-
compliant.

Members -- The value of a literal static is 13


specified through the use of
field initialization metadata.
A CLS-compliant literal must
have a value specified in field
initialization metadata that is
of exactly the same type as
the literal (or of the
underlying type, if that literal
is an enum ).

Members Type members in general The vararg constraint is not 15


part of the CLS, and the only
calling convention
supported by the CLS is the
standard managed calling
convention.

Naming conventions Naming conventions Assemblies shall follow 4


Annex 7 of Technical Report
15 of the Unicode
Standard3.0 governing the
set of characters permitted
to start and be included in
identifiers, available onlineat
http://www.unicode.org/unic
ode/reports/tr15/tr15-
18.html. Identifiers shall be
in thecanonical format
defined by Unicode
Normalization Form C. For
CLS purposes, two
identifiersare the same if
their lowercase mappings (as
specified by the Unicode
locale-insensitive, one-
toonelowercase mappings)
are the same. That is, for
two identifiers to be
considered differentunder
the CLS they shall differ in
more than simply their case.
However, in order to
override aninherited
definition the CLI requires
the precise encoding of the
original declaration be used.
CATEGORY SEE RULE RULE NUMBER

Overloading Naming conventions All names introduced in a 5


CLS-compliant scope shall
be distinct independent
ofkind, except where the
names are identical and
resolved via overloading.
That is, while the CTSallows
a single type to use the
same name for a method
and a field, the CLS does
not.

Overloading Naming conventions Fields and nested types shall 6


be distinct by identifier
comparison alone,
eventhough the CTS allows
distinct signatures to be
distinguished. Methods,
properties, and eventsthat
have the same name (by
identifier comparison) shall
differ by more than just the
return type,except as
specified in CLS Rule 39.

Overloading Overloads Only properties and 37


methods can be overloaded.

Overloading Overloads Properties and methods can 38


be overloaded based only
on the number and types of
their parameters, except the
conversion operators named
op_Implicit and
op_Explicit , which can
also be overloaded based on
their return type.

Overloading -- If two or more CLS- 48


compliant methods declared
in a type have the same
nameand, for a specific set
of type instantiations, they
have the same parameter
and return types, thenall
these methods shall be
semantically equivalent at
those type instantiations.

Types Type and type member System.Object is CLS- 23


signatures compliant. Any other CLS-
compliant class shall inherit
from a CLS-compliant class.
CATEGORY SEE RULE RULE NUMBER

Properties Properties The methods that 24


implement the getter and
setter methods of a
property shallbe marked
SpecialName in the
metadata.

Properties Properties A property’s accessors shall 26


all be static, all be virtual, or
all be instance.

Properties Properties The type of a property shall 27


be the return type of the
getter and the type of the
last argument of the setter.
The types of the parameters
of the property shall be the
types of the parameters to
the getter and the types of
all but the final parameter of
the setter. All of these types
shall be CLS-compliant, and
shall not be managed
pointers (i.e., shall not be
passed by reference).

Properties Properties Properties shall adhere to a 28


specific naming pattern. The
SpecialName attribute
referred to in CLS rule 24
shall be ignored in
appropriate name
comparisons and shall
adhere to identifier rules. A
property shall have a getter
method, a setter method, or
both.

Type conversion Type conversion If either op_Implicit or 39


op_Explicit is provided,
an alternate means of
providing the coercion shall
be provided.

Types Type and type member Boxed value types are not 3
signatures CLS-compliant.

Types Type and type member All types appearing in a 11


signatures signature shall be CLS-
compliant. All types
composing an instantiated
generic type shall be CLS-
compliant.

Types Type and type member Typed references are not 14


signatures CLS-compliant.
CATEGORY SEE RULE RULE NUMBER

Types Type and type member Unmanaged pointer types 17


signatures are not CLS-compliant.

Types Type and type member CLS-compliant classes, value 20


signatures types, and interfaces shall
not require the
implementation of non-CLS-
compliant members.

Types and type member signatures


The System.Object type is CLS-compliant and is the base type of all object types in the .NET Framework type
system. Inheritance in the .NET Framework is either implicit (for example, the String class implicitly inherits from
the Object class) or explicit (for example, the CultureNotFoundException class explicitly inherits from the
ArgumentException class, which explicitly inherits from the SystemException class, which explicitly inherits from
the Exception class). For a derived type to be CLS compliant, its base type must also be CLS-compliant.
The following example shows a derived type whose base type is not CLS-compliant. It defines a base Counter
class that uses an unsigned 32-bit integer as a counter. Because the class provides counter functionality by
wrapping an unsigned integer, the class is marked as non-CLS-compliant. As a result, a derived class,
NonZeroCounter , is also not CLS-compliant.
using System;

[assembly: CLSCompliant(true)]

[CLSCompliant(false)]
public class Counter
{
UInt32 ctr;

public Counter()
{
ctr = 0;
}

protected Counter(UInt32 ctr)


{
this.ctr = ctr;
}

public override string ToString()


{
return String.Format("{0}). ", ctr);
}

public UInt32 Value


{
get { return ctr; }
}

public void Increment()


{
ctr += (uint) 1;
}
}

public class NonZeroCounter : Counter


{
public NonZeroCounter(int startIndex) : this((uint) startIndex)
{
}

private NonZeroCounter(UInt32 startIndex) : base(startIndex)


{
}
}
// Compilation produces a compiler warning like the following:
// Type3.cs(37,14): warning CS3009: 'NonZeroCounter': base type 'Counter' is not
// CLS-compliant
// Type3.cs(7,14): (Location of symbol related to previous warning)
<Assembly: CLSCompliant(True)>

<CLSCompliant(False)> _
Public Class Counter
Dim ctr As UInt32

Public Sub New


ctr = 0
End Sub

Protected Sub New(ctr As UInt32)


ctr = ctr
End Sub

Public Overrides Function ToString() As String


Return String.Format("{0}). ", ctr)
End Function

Public ReadOnly Property Value As UInt32


Get
Return ctr
End Get
End Property

Public Sub Increment()


ctr += CType(1, UInt32)
End Sub
End Class

Public Class NonZeroCounter : Inherits Counter


Public Sub New(startIndex As Integer)
MyClass.New(CType(startIndex, UInt32))
End Sub

Private Sub New(startIndex As UInt32)


MyBase.New(CType(startIndex, UInt32))
End Sub
End Class
' Compilation produces a compiler warning like the following:
' Type3.vb(34) : warning BC40026: 'NonZeroCounter' is not CLS-compliant
' because it derives from 'Counter', which is not CLS-compliant.
'
' Public Class NonZeroCounter : Inherits Counter
' ~~~~~~~~~~~~~~

All types that appear in member signatures, including a method's return type or a property type, must be CLS-
compliant. In addition, for generic types:
All types that compose an instantiated generic type must be CLS-compliant.
All types used as constraints on generic parameters must be CLS-compliant.
The .NET Framework common type system includes a number of built-in types that are supported directly by the
common language runtime and are specially encoded in an assembly's metadata. Of these intrinsic types, the
types listed in the following table are CLS-compliant.

CLS-COMPLIANT TYPE DESCRIPTION

Byte 8-bit unsigned integer

Int16 16-bit signed integer


CLS-COMPLIANT TYPE DESCRIPTION

Int32 32-bit signed integer

Int64 64-bit signed integer

Single Single-precision floating-point value

Double Double-precision floating-point value

Boolean true or false value type

Char UTF-16 encoded code unit

Decimal Non-floating-point decimal number

IntPtr Pointer or handle of a platform-defined size

String Collection of zero, one, or more Char objects

The intrinsic types listed in the following table are not CLS-Compliant.

NON-COMPLIANT TYPE DESCRIPTION CLS-COMPLIANT ALTERNATIVE

SByte 8-bit signed integer data type Int16

TypedReference Pointer to an object and its runtime None


type

UInt16 16-bit unsigned integer Int32

UInt32 32-bit unsigned integer Int64

UInt64 64-bit unsigned integer Int64 (may overflow), BigInteger, or


Double

UIntPtr Unsigned pointer or handle IntPtr

The .NET Framework Class Library or any other class library may include other types that aren't CLS-compliant; for
example:
Boxed value types. The following C# example creates a class that has a public property of type int* named
Value . Because an int* is a boxed value type, the compiler flags it as non-CLS-compliant.
using System;

[assembly:CLSCompliant(true)]

public unsafe class TestClass


{
private int* val;

public TestClass(int number)


{
val = (int*) number;
}

public int* Value {


get { return val; }
}
}
// The compiler generates the following output when compiling this example:
// warning CS3003: Type of 'TestClass.Value' is not CLS-compliant

Typed references, which are special constructs that contain a reference to an object and a reference to a
type. Typed references are represented in the .NET Framework by the TypedReference class.
If a type is not CLS-compliant, you should apply the CLSCompliantAttribute attribute with an isCompliant value of
false to it. For more information, see the The CLSCompliantAttribute attribute section.

The following example illustrates the problem of CLS compliance in a method signature and in generic type
instantiation. It defines an InvoiceItem class with a property of type UInt32, a property of type
Nullable(Of UInt32) , and a constructor with parameters of type UInt32 and Nullable(Of UInt32) . You get four
compiler warnings when you try to compile this example.
using System;

[assembly: CLSCompliant(true)]

public class InvoiceItem


{
private uint invId = 0;
private uint itemId = 0;
private Nullable<uint> qty;

public InvoiceItem(uint sku, Nullable<uint> quantity)


{
itemId = sku;
qty = quantity;
}

public Nullable<uint> Quantity


{
get { return qty; }
set { qty = value; }
}

public uint InvoiceId


{
get { return invId; }
set { invId = value; }
}
}
// The attempt to compile the example displays the following output:
// Type1.cs(13,23): warning CS3001: Argument type 'uint' is not CLS-compliant
// Type1.cs(13,33): warning CS3001: Argument type 'uint?' is not CLS-compliant
// Type1.cs(19,26): warning CS3003: Type of 'InvoiceItem.Quantity' is not CLS-compliant
// Type1.cs(25,16): warning CS3003: Type of 'InvoiceItem.InvoiceId' is not CLS-compliant
<Assembly: CLSCompliant(True)>

Public Class InvoiceItem

Private invId As UInteger = 0


Private itemId As UInteger = 0
Private qty AS Nullable(Of UInteger)

Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))


itemId = sku
qty = quantity
End Sub

Public Property Quantity As Nullable(Of UInteger)


Get
Return qty
End Get
Set
qty = value
End Set
End Property

Public Property InvoiceId As UInteger


Get
Return invId
End Get
Set
invId = value
End Set
End Property
End Class
' The attempt to compile the example displays output similar to the following:
' Type1.vb(13) : warning BC40028: Type of parameter 'sku' is not CLS-compliant.
'
' Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))
' ~~~
' Type1.vb(13) : warning BC40041: Type 'UInteger' is not CLS-compliant.
'
' Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))
' ~~~~~~~~
' Type1.vb(18) : warning BC40041: Type 'UInteger' is not CLS-compliant.
'
' Public Property Quantity As Nullable(Of UInteger)
' ~~~~~~~~
' Type1.vb(27) : warning BC40027: Return type of function 'InvoiceId' is not CLS-compliant.
'
' Public Property InvoiceId As UInteger
' ~~~~~~~~~

To eliminate the compiler warnings, replace the non-CLS-compliant types in the InvoiceItem public interface with
compliant types:
using System;

[assembly: CLSCompliant(true)]

public class InvoiceItem


{
private uint invId = 0;
private uint itemId = 0;
private Nullable<int> qty;

public InvoiceItem(int sku, Nullable<int> quantity)


{
if (sku <= 0)
throw new ArgumentOutOfRangeException("The item number is zero or negative.");
itemId = (uint) sku;

qty = quantity;
}

public Nullable<int> Quantity


{
get { return qty; }
set { qty = value; }
}

public int InvoiceId


{
get { return (int) invId; }
set {
if (value <= 0)
throw new ArgumentOutOfRangeException("The invoice number is zero or negative.");
invId = (uint) value; }
}
}
<Assembly: CLSCompliant(True)>

Public Class InvoiceItem

Private invId As UInteger = 0


Private itemId As UInteger = 0
Private qty AS Nullable(Of Integer)

Public Sub New(sku As Integer, quantity As Nullable(Of Integer))


If sku <= 0 Then
Throw New ArgumentOutOfRangeException("The item number is zero or negative.")
End If
itemId = CUInt(sku)
qty = quantity
End Sub

Public Property Quantity As Nullable(Of Integer)


Get
Return qty
End Get
Set
qty = value
End Set
End Property

Public Property InvoiceId As Integer


Get
Return CInt(invId)
End Get
Set
invId = CUInt(value)
End Set
End Property
End Class

In addition to the specific types listed, some categories of types are not CLS compliant. These include unmanaged
pointer types and function pointer types. The following example generates a compiler warning because it uses a
pointer to an integer to create an array of integers.

using System;

[assembly: CLSCompliant(true)]

public class ArrayHelper


{
unsafe public static Array CreateInstance(Type type, int* ptr, int items)
{
Array arr = Array.CreateInstance(type, items);
int* addr = ptr;
for (int ctr = 0; ctr < items; ctr++) {
int value = *addr;
arr.SetValue(value, ctr);
addr++;
}
return arr;
}
}
// The attempt to compile this example displays the following output:
// UnmanagedPtr1.cs(8,57): warning CS3001: Argument type 'int*' is not CLS-compliant

For CLS-compliant abstract classes (that is, classes marked as abstract in C# or as MustInherit in Visual Basic),
all members of the class must also be CLS-compliant.
Naming conventions
Because some programming languages are case-insensitive, identifiers (such as the names of namespaces, types,
and members) must differ by more than case. Two identifiers are considered equivalent if their lowercase
mappings are the same. The following C# example defines two public classes, Person and person . Because they
differ only by case, the C# compiler flags them as not CLS-compliant.

using System;

[assembly: CLSCompliant(true)]

public class Person : person


{

public class person


{

}
// Compilation produces a compiler warning like the following:
// Naming1.cs(11,14): warning CS3005: Identifier 'person' differing
// only in case is not CLS-compliant
// Naming1.cs(6,14): (Location of symbol related to previous warning)

Programming language identifiers, such as the names of namespaces, types, and members, must conform to the
Unicode Standard 3.0, Technical Report 15, Annex 7. This means that:
The first character of an identifier can be any Unicode uppercase letter, lowercase letter, title case letter,
modifier letter, other letter, or letter number. For information on Unicode character categories, see the
System.Globalization.UnicodeCategory enumeration.
Subsequent characters can be from any of the categories as the first character, and can also include non-
spacing marks, spacing combining marks, decimal numbers, connector punctuations, and formatting codes.
Before you compare identifiers, you should filter out formatting codes and convert the identifiers to Unicode
Normalization Form C, because a single character can be represented by multiple UTF-16-encoded code units.
Character sequences that produce the same code units in Unicode Normalization Form C are not CLS-compliant.
The following example defines a property named Å , which consists of the character ANGSTROM SIGN (U+212B),
and a second property named Å , which consists of the character LATIN CAPITAL LETTER A WITH RING ABOVE
(U+00C5). Both the C# and Visual Basic compilers flag the source code as non-CLS-compliant.
public class Size
{
private double a1;
private double a2;

public double Å
{
get { return a1; }
set { a1 = value; }
}

public double Å
{
get { return a2; }
set { a2 = value; }
}
}
// Compilation produces a compiler warning like the following:
// Naming2a.cs(16,18): warning CS3005: Identifier 'Size.Å' differing only in case is not
// CLS-compliant
// Naming2a.cs(10,18): (Location of symbol related to previous warning)
// Naming2a.cs(18,8): warning CS3005: Identifier 'Size.Å.get' differing only in case is not
// CLS-compliant
// Naming2a.cs(12,8): (Location of symbol related to previous warning)
// Naming2a.cs(19,8): warning CS3005: Identifier 'Size.Å.set' differing only in case is not
// CLS-compliant
// Naming2a.cs(13,8): (Location of symbol related to previous warning)

<Assembly: CLSCompliant(True)>
Public Class Size
Private a1 As Double
Private a2 As Double

Public Property Å As Double


Get
Return a1
End Get
Set
a1 = value
End Set
End Property

Public Property Å As Double


Get
Return a2
End Get
Set
a2 = value
End Set
End Property
End Class
' Compilation produces a compiler warning like the following:
' Naming1.vb(9) : error BC30269: 'Public Property Å As Double' has multiple definitions
' with identical signatures.
'
' Public Property Å As Double
' ~

Member names within a particular scope (such as the namespaces within an assembly, the types within a
namespace, or the members within a type) must be unique except for names that are resolved through
overloading. This requirement is more stringent than that of the common type system, which allows multiple
members within a scope to have identical names as long as they are different kinds of members (for example, one
is a method and one is a field). In particular, for type members:
Fields and nested types are distinguished by name alone.
Methods, properties, and events that have the same name must differ by more than just return type.
The following example illustrates the requirement that member names must be unique within their scope. It
defines a class named Converter that includes four members named Conversion . Three are methods, and one is a
property. The method that includes an Int64 parameter is uniquely named, but the two methods with an Int32
parameter are not, because return value is not considered a part of a member's signature. The Conversion
property also violates this requirement, because properties cannot have the same name as overloaded methods.

using System;

[assembly: CLSCompliant(true)]

public class Converter


{
public double Conversion(int number)
{
return (double) number;
}

public float Conversion(int number)


{
return (float) number;
}

public double Conversion(long number)


{
return (double) number;
}

public bool Conversion


{
get { return true; }
}
}
// Compilation produces a compiler error like the following:
// Naming3.cs(13,17): error CS0111: Type 'Converter' already defines a member called
// 'Conversion' with the same parameter types
// Naming3.cs(8,18): (Location of symbol related to previous error)
// Naming3.cs(23,16): error CS0102: The type 'Converter' already contains a definition for
// 'Conversion'
// Naming3.cs(8,18): (Location of symbol related to previous error)
<Assembly: CLSCompliant(True)>

Public Class Converter


Public Function Conversion(number As Integer) As Double
Return CDbl(number)
End Function

Public Function Conversion(number As Integer) As Single


Return CSng(number)
End Function

Public Function Conversion(number As Long) As Double


Return CDbl(number)
End Function

Public ReadOnly Property Conversion As Boolean


Get
Return True
End Get
End Property
End Class
' Compilation produces a compiler error like the following:
' Naming3.vb(8) : error BC30301: 'Public Function Conversion(number As Integer) As Double'
' and 'Public Function Conversion(number As Integer) As Single' cannot
' overload each other because they differ only by return types.
'
' Public Function Conversion(number As Integer) As Double
' ~~~~~~~~~~
' Naming3.vb(20) : error BC30260: 'Conversion' is already declared as 'Public Function
' Conversion(number As Integer) As Single' in this class.
'
' Public ReadOnly Property Conversion As Boolean
' ~~~~~~~~~~

Individual languages include unique keywords, so languages that target the common language runtime must also
provide some mechanism for referencing identifiers (such as type names) that coincide with keywords. For
example, case is a keyword in both C# and Visual Basic. However, the following Visual Basic example is able to
disambiguate a class named case from the case keyword by using opening and closing braces. Otherwise, the
example would produce the error message, "Keyword is not valid as an identifier," and fail to compile.

Public Class [case]


Private _id As Guid
Private name As String

Public Sub New(name As String)


_id = Guid.NewGuid()
Me.name = name
End Sub

Public ReadOnly Property ClientName As String


Get
Return name
End Get
End Property
End Class

The following C# example is able to instantiate the case class by using the @ symbol to disambiguate the
identifier from the language keyword. Without it, the C# compiler would display two error messages, "Type
expected" and "Invalid expression term 'case'."
using System;

public class Example


{
public static void Main()
{
@case c = new @case("John");
Console.WriteLine(c.ClientName);
}
}

Type conversion
The Common Language Specification defines two conversion operators:
op_Implicit, which is used for widening conversions that do not result in loss of data or precision. For
example, the Decimal structure includes an overloaded op_Implicit operator to convert values of integral
types and Char values to Decimal values.
op_Explicit , which is used for narrowing conversions that can result in loss of magnitude (a value is
converted to a value that has a smaller range) or precision. For example, the Decimal structure includes an
overloaded op_Explicit operator to convert Double and Single values to Decimal and to convert Decimal
values to integral values, Double, Single, and Char.
However, not all languages support operator overloading or the definition of custom operators. If you choose to
implement these conversion operators, you should also provide an alternate way to perform the conversion. We
recommend that you provide From Xxx and To Xxx methods.
The following example defines CLS-compliant implicit and explicit conversions. It creates a UDouble class that
represents an signed double-precision, floating-point number. It provides for implicit conversions from UDouble
to Double and for explicit conversions from UDouble to Single, Double to UDouble , and Single to UDouble . It also
defines a ToDouble method as an alternative to the implicit conversion operator and the ToSingle , FromDouble ,
and FromSingle methods as alternatives to the explicit conversion operators.

using System;

public struct UDouble


{
private double number;

public UDouble(double value)


{
if (value < 0)
throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

number = value;
}

public UDouble(float value)


{
if (value < 0)
throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

number = value;
}

public static readonly UDouble MinValue = (UDouble) 0.0;


public static readonly UDouble MaxValue = (UDouble) Double.MaxValue;

public static explicit operator Double(UDouble value)


{
return value.number;
}

public static implicit operator Single(UDouble value)


{
if (value.number > (double) Single.MaxValue)
throw new InvalidCastException("A UDouble value is out of range of the Single type.");

return (float) value.number;


}

public static explicit operator UDouble(double value)


{
if (value < 0)
throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

return new UDouble(value);


}

public static implicit operator UDouble(float value)


{
if (value < 0)
throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

return new UDouble(value);


}

public static Double ToDouble(UDouble value)


{
return (Double) value;
}

public static float ToSingle(UDouble value)


{
return (float) value;
}

public static UDouble FromDouble(double value)


{
return new UDouble(value);
}

public static UDouble FromSingle(float value)


{
return new UDouble(value);
}
}
Public Structure UDouble
Private number As Double

Public Sub New(value As Double)


If value < 0 Then
Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
End If
number = value
End Sub

Public Sub New(value As Single)


If value < 0 Then
Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
End If
number = value
End Sub

Public Shared ReadOnly MinValue As UDouble = CType(0.0, UDouble)


Public Shared ReadOnly MaxValue As UDouble = Double.MaxValue

Public Shared Widening Operator CType(value As UDouble) As Double


Return value.number
End Operator

Public Shared Narrowing Operator CType(value As UDouble) As Single


If value.number > CDbl(Single.MaxValue) Then
Throw New InvalidCastException("A UDouble value is out of range of the Single type.")
End If
Return CSng(value.number)
End Operator

Public Shared Narrowing Operator CType(value As Double) As UDouble


If value < 0 Then
Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
End If
Return New UDouble(value)
End Operator

Public Shared Narrowing Operator CType(value As Single) As UDouble


If value < 0 Then
Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
End If
Return New UDouble(value)
End Operator

Public Shared Function ToDouble(value As UDouble) As Double


Return CType(value, Double)
End Function

Public Shared Function ToSingle(value As UDouble) As Single


Return CType(value, Single)
End Function

Public Shared Function FromDouble(value As Double) As UDouble


Return New UDouble(value)
End Function

Public Shared Function FromSingle(value As Single) As UDouble


Return New UDouble(value)
End Function
End Structure

Arrays
CLS-compliant arrays conform to the following rules:
All dimensions of an array must have a lower bound of zero. The following example creates a non-CLS-
compliant array with a lower bound of one. Note that, despite the presence of the CLSCompliantAttribute
attribute, the compiler does not detect that the array returned by the Numbers.GetTenPrimes method is not
CLS-compliant.

[assembly: CLSCompliant(true)]

public class Numbers


{
public static Array GetTenPrimes()
{
Array arr = Array.CreateInstance(typeof(Int32), new int[] {10}, new int[] {1});
arr.SetValue(1, 1);
arr.SetValue(2, 2);
arr.SetValue(3, 3);
arr.SetValue(5, 4);
arr.SetValue(7, 5);
arr.SetValue(11, 6);
arr.SetValue(13, 7);
arr.SetValue(17, 8);
arr.SetValue(19, 9);
arr.SetValue(23, 10);

return arr;
}
}

<Assembly: CLSCompliant(True)>

Public Class Numbers


Public Shared Function GetTenPrimes() As Array
Dim arr As Array = Array.CreateInstance(GetType(Int32), {10}, {1})
arr.SetValue(1, 1)
arr.SetValue(2, 2)
arr.SetValue(3, 3)
arr.SetValue(5, 4)
arr.SetValue(7, 5)
arr.SetValue(11, 6)
arr.SetValue(13, 7)
arr.SetValue(17, 8)
arr.SetValue(19, 9)
arr.SetValue(23, 10)

Return arr
End Function
End Class

All array elements must consist of CLS-compliant types. The following example defines two methods that
return non-CLS-compliant arrays. The first returns an array of UInt32 values. The second returns an Object
array that includes Int32 and UInt32 values. Although the compiler identifies the first array as non-
compliant because of its UInt32 type, it fails to recognize that the second array includes non-CLS-compliant
elements.
using System;

[assembly: CLSCompliant(true)]

public class Numbers


{
public static UInt32[] GetTenPrimes()
{
uint[] arr = { 1u, 2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u };
return arr;
}

public static Object[] GetFivePrimes()


{
Object[] arr = { 1, 2, 3, 5u, 7u };
return arr;
}
}
// Compilation produces a compiler warning like the following:
// Array2.cs(8,27): warning CS3002: Return type of 'Numbers.GetTenPrimes()' is not
// CLS-compliant

<Assembly: CLSCompliant(True)>

Public Class Numbers


Public Shared Function GetTenPrimes() As UInt32()
Return { 1ui, 2ui, 3ui, 5ui, 7ui, 11ui, 13ui, 17ui, 19ui }
End Function

Public Shared Function GetFivePrimes() As Object()


Dim arr() As Object = { 1, 2, 3, 5ui, 7ui }
Return arr
End Function
End Class
' Compilation produces a compiler warning like the following:
' warning BC40027: Return type of function 'GetTenPrimes' is not CLS-compliant.
'
' Public Shared Function GetTenPrimes() As UInt32()
' ~~~~~~~~~~~~

Overload resolution for methods that have array parameters is based on the fact that they are arrays and on
their element type. For this reason, the following definition of an overloaded GetSquares method is CLS-
compliant.
using System;
using System.Numerics;

[assembly: CLSCompliant(true)]

public class Numbers


{
public static byte[] GetSquares(byte[] numbers)
{
byte[] numbersOut = new byte[numbers.Length];
for (int ctr = 0; ctr < numbers.Length; ctr++) {
int square = ((int) numbers[ctr]) * ((int) numbers[ctr]);
if (square <= Byte.MaxValue)
numbersOut[ctr] = (byte) square;
// If there's an overflow, assign MaxValue to the corresponding
// element.
else
numbersOut[ctr] = Byte.MaxValue;

}
return numbersOut;
}

public static BigInteger[] GetSquares(BigInteger[] numbers)


{
BigInteger[] numbersOut = new BigInteger[numbers.Length];
for (int ctr = 0; ctr < numbers.Length; ctr++)
numbersOut[ctr] = numbers[ctr] * numbers[ctr];

return numbersOut;
}
}

Imports System.Numerics

<Assembly: CLSCompliant(True)>

Public Module Numbers


Public Function GetSquares(numbers As Byte()) As Byte()
Dim numbersOut(numbers.Length - 1) As Byte
For ctr As Integer = 0 To numbers.Length - 1
Dim square As Integer = (CInt(numbers(ctr)) * CInt(numbers(ctr)))
If square <= Byte.MaxValue Then
numbersOut(ctr) = CByte(square)
' If there's an overflow, assign MaxValue to the corresponding
' element.
Else
numbersOut(ctr) = Byte.MaxValue
End If
Next
Return numbersOut
End Function

Public Function GetSquares(numbers As BigInteger()) As BigInteger()


Dim numbersOut(numbers.Length - 1) As BigInteger
For ctr As Integer = 0 To numbers.Length - 1
numbersOut(ctr) = numbers(ctr) * numbers(ctr)
Next
Return numbersOut
End Function
End Module

Interfaces
CLS-compliant interfaces can define properties, events, and virtual methods (methods with no implementation). A
CLS-compliant interface cannot have any of the following:
Static methods or static fields. Both the C# and Visual Basic compilers generate compiler errors if you define
a static member in an interface.
Fields. Both the C# and Visual Basic compilers generate compiler errors if you define a field in an interface.
Methods that are not CLS-compliant. For example, the following interface definition includes a method,
INumber.GetUnsigned , that is marked as non-CLS-compliant. This example generates a compiler warning.

using System;

[assembly:CLSCompliant(true)]

public interface INumber


{
int Length();
[CLSCompliant(false)] ulong GetUnsigned();
}
// Attempting to compile the example displays output like the following:
// Interface2.cs(8,32): warning CS3010: 'INumber.GetUnsigned()': CLS-compliant interfaces
// must have only CLS-compliant members

<Assembly: CLSCompliant(True)>

Public Interface INumber


Function Length As Integer

<CLSCompliant(False)> Function GetUnsigned As ULong


End Interface
' Attempting to compile the example displays output like the following:
' Interface2.vb(9) : warning BC40033: Non CLS-compliant 'function' is not allowed in a
' CLS-compliant interface.
'
' <CLSCompliant(False)> Function GetUnsigned As ULong
' ~~~~~~~~~~~

Because of this rule, CLS-compliant types are not required to implement non-CLS-compliant members. If a
CLS-compliant framework does expose a class that implements a non-CLS compliant interface, it should
also provide concrete implementations of all non-CLS-compliant members.
CLS-compliant language compilers must also allow a class to provide separate implementations of members that
have the same name and signature in multiple interfaces. Both C# and Visual Basic support explicit interface
implementations to provide different implementations of identically named methods. Visual Basic also supports
the Implements keyword, which enables you to explicitly designate which interface and member a particular
member implements. The following example illustrates this scenario by defining a Temperature class that
implements the ICelsius and IFahrenheit interfaces as explicit interface implementations.
using System;

[assembly: CLSCompliant(true)]

public interface IFahrenheit


{
decimal GetTemperature();
}

public interface ICelsius


{
decimal GetTemperature();
}

public class Temperature : ICelsius, IFahrenheit


{
private decimal _value;

public Temperature(decimal value)


{
// We assume that this is the Celsius value.
_value = value;
}

decimal IFahrenheit.GetTemperature()
{
return _value * 9 / 5 + 32;
}

decimal ICelsius.GetTemperature()
{
return _value;
}
}
public class Example
{
public static void Main()
{
Temperature temp = new Temperature(100.0m);
ICelsius cTemp = temp;
IFahrenheit fTemp = temp;
Console.WriteLine("Temperature in Celsius: {0} degrees",
cTemp.GetTemperature());
Console.WriteLine("Temperature in Fahrenheit: {0} degrees",
fTemp.GetTemperature());
}
}
// The example displays the following output:
// Temperature in Celsius: 100.0 degrees
// Temperature in Fahrenheit: 212.0 degrees
<Assembly: CLSCompliant(True)>

Public Interface IFahrenheit


Function GetTemperature() As Decimal
End Interface

Public Interface ICelsius


Function GetTemperature() As Decimal
End Interface

Public Class Temperature : Implements ICelsius, IFahrenheit


Private _value As Decimal

Public Sub New(value As Decimal)


' We assume that this is the Celsius value.
_value = value
End Sub

Public Function GetFahrenheit() As Decimal _


Implements IFahrenheit.GetTemperature
Return _value * 9 / 5 + 32
End Function

Public Function GetCelsius() As Decimal _


Implements ICelsius.GetTemperature
Return _value
End Function
End Class

Module Example
Public Sub Main()
Dim temp As New Temperature(100.0d)
Console.WriteLine("Temperature in Celsius: {0} degrees",
temp.GetCelsius())
Console.WriteLine("Temperature in Fahrenheit: {0} degrees",
temp.GetFahrenheit())
End Sub
End Module
' The example displays the following output:
' Temperature in Celsius: 100.0 degrees
' Temperature in Fahrenheit: 212.0 degrees

Enumerations
CLS-compliant enumerations must follow these rules:
The underlying type of the enumeration must be an intrinsic CLS-compliant integer (Byte, Int16, Int32, or
Int64). For example, the following code tries to define an enumeration whose underlying type is UInt32 and
generates a compiler warning.
using System;

[assembly: CLSCompliant(true)]

public enum Size : uint {


Unspecified = 0,
XSmall = 1,
Small = 2,
Medium = 3,
Large = 4,
XLarge = 5
};

public class Clothing


{
public string Name;
public string Type;
public string Size;
}
// The attempt to compile the example displays a compiler warning like the following:
// Enum3.cs(6,13): warning CS3009: 'Size': base type 'uint' is not CLS-compliant

<Assembly: CLSCompliant(True)>

Public Enum Size As UInt32


Unspecified = 0
XSmall = 1
Small = 2
Medium = 3
Large = 4
XLarge = 5
End Enum

Public Class Clothing


Public Name As String
Public Type As String
Public Size As Size
End Class
' The attempt to compile the example displays a compiler warning like the following:
' Enum3.vb(6) : warning BC40032: Underlying type 'UInt32' of Enum is not CLS-compliant.
'
' Public Enum Size As UInt32
' ~~~~

An enumeration type must have a single instance field named Value__ that is marked with the
System.Reflection.FieldAttributes.RTSpecialName attribute. This enables you to reference the field value
implicitly.
An enumeration includes literal static fields whose types match the type of the enumeration itself. For
example, if you define a State enumeration with values of State.On and State.Off , State.On and
State.Off are both literal static fields whose type is State .

There are two kinds of enumerations:


An enumeration that represents a set of mutually exclusive, named integer values. This type of
enumeration is indicated by the absence of the System.FlagsAttribute custom attribute.
An enumeration that represents a set of bit flags that can combine to generate an unnamed value.
This type of enumeration is indicated by the presence of the System.FlagsAttribute custom attribute.
For more information, see the documentation for the Enum structure.
The value of an enumeration is not limited to the range of its specified values. In other words, the range of
values in an enumeration is the range of its underlying value. You can use the System.Enum.IsDefined
method to determine whether a specified value is a member of an enumeration.
Type members in general
The Common Language Specification requires all fields and methods to be accessed as members of a particular
class. Therefore, global static fields and methods (that is, static fields or methods that are defined apart from a
type) are not CLS-compliant. If you try to include a global field or method in your source code, both the C# and
Visual Basic compilers generate a compiler error.
The Common Language Specification supports only the standard managed calling convention. It doesn't support
unmanaged calling conventions and methods with variable argument lists marked with the varargs keyword. For
variable argument lists that are compatible with the standard managed calling convention, use the
ParamArrayAttribute attribute or the individual language's implementation, such as the params keyword in C#
and the ParamArray keyword in Visual Basic.
Member accessibility
Overriding an inherited member cannot change the accessibility of that member. For example, a public method in
a base class cannot be overridden by a private method in a derived class. There is one exception: a
protected internal (in C#) or Protected Friend (in Visual Basic) member in one assembly that is overridden by a
type in a different assembly. In that case, the accessibility of the override is Protected .
The following example illustrates the error that is generated when the CLSCompliantAttribute attribute is set to
true , and Person , which is a class derived from Animal , tries to change the accessibility of the Species property
from public to private. The example compiles successfully if its accessibility is changed to public.
using System;

[assembly: CLSCompliant(true)]

public class Animal


{
private string _species;

public Animal(string species)


{
_species = species;
}

public virtual string Species


{
get { return _species; }
}

public override string ToString()


{
return _species;
}
}

public class Human : Animal


{
private string _name;

public Human(string name) : base("Homo Sapiens")


{
_name = name;
}

public string Name


{
get { return _name; }
}

private override string Species


{
get { return base.Species; }
}

public override string ToString()


{
return _name;
}
}

public class Example


{
public static void Main()
{
Human p = new Human("John");
Console.WriteLine(p.Species);
Console.WriteLine(p.ToString());
}
}
// The example displays the following output:
// error CS0621: 'Human.Species': virtual or abstract members cannot be private
<Assembly: CLSCompliant(True)>

Public Class Animal


Private _species As String

Public Sub New(species As String)


_species = species
End Sub

Public Overridable ReadOnly Property Species As String


Get
Return _species
End Get
End Property

Public Overrides Function ToString() As String


Return _species
End Function
End Class

Public Class Human : Inherits Animal


Private _name As String

Public Sub New(name As String)


MyBase.New("Homo Sapiens")
_name = name
End Sub

Public ReadOnly Property Name As String


Get
Return _name
End Get
End Property

Private Overrides ReadOnly Property Species As String


Get
Return MyBase.Species
End Get
End Property

Public Overrides Function ToString() As String


Return _name
End Function
End Class

Public Module Example


Public Sub Main()
Dim p As New Human("John")
Console.WriteLine(p.Species)
Console.WriteLine(p.ToString())
End Sub
End Module
' The example displays the following output:
' 'Private Overrides ReadOnly Property Species As String' cannot override
' 'Public Overridable ReadOnly Property Species As String' because
' they have different access levels.
'
' Private Overrides ReadOnly Property Species As String

Types in the signature of a member must be accessible whenever that member is accessible. For example, this
means that a public member cannot include a parameter whose type is private, protected, or internal. The
following example illustrates the compiler error that results when a StringWrapper class constructor exposes an
internal StringOperationType enumeration value that determines how a string value should be wrapped.
using System;
using System.Text;

public class StringWrapper


{
string internalString;
StringBuilder internalSB = null;
bool useSB = false;

public StringWrapper(StringOperationType type)


{
if (type == StringOperationType.Normal) {
useSB = false;
}
else {
useSB = true;
internalSB = new StringBuilder();
}
}

// The remaining source code...


}

internal enum StringOperationType { Normal, Dynamic }


// The attempt to compile the example displays the following output:
// error CS0051: Inconsistent accessibility: parameter type
// 'StringOperationType' is less accessible than method
// 'StringWrapper.StringWrapper(StringOperationType)'

Imports System.Text

<Assembly:CLSCompliant(True)>

Public Class StringWrapper

Dim internalString As String


Dim internalSB As StringBuilder = Nothing
Dim useSB As Boolean = False

Public Sub New(type As StringOperationType)


If type = StringOperationType.Normal Then
useSB = False
Else
internalSB = New StringBuilder()
useSB = True
End If
End Sub

' The remaining source code...


End Class

Friend Enum StringOperationType As Integer


Normal = 0
Dynamic = 1
End Enum
' The attempt to compile the example displays the following output:
' error BC30909: 'type' cannot expose type 'StringOperationType'
' outside the project through class 'StringWrapper'.
'
' Public Sub New(type As StringOperationType)
' ~~~~~~~~~~~~~~~~~~~

Generic types and members


Nested types always have at least as many generic parameters as their enclosing type. These correspond by
position to the generic parameters in the enclosing type. The generic type can also include new generic
parameters.
The relationship between the generic type parameters of a containing type and its nested types may be hidden by
the syntax of individual languages. In the following example, a generic type Outer<T> contains two nested classes,
Inner1A and Inner1B<U> . The calls to the ToString method, which each class inherits from
System.Object.ToString, show that each nested class includes the type parameters of its containing class.

using System;

[assembly:CLSCompliant(true)]

public class Outer<T>


{
T value;

public Outer(T value)


{
this.value = value;
}

public class Inner1A : Outer<T>


{
public Inner1A(T value) : base(value)
{ }
}

public class Inner1B<U> : Outer<T>


{
U value2;

public Inner1B(T value1, U value2) : base(value1)


{
this.value2 = value2;
}
}
}

public class Example


{
public static void Main()
{
var inst1 = new Outer<String>("This");
Console.WriteLine(inst1);

var inst2 = new Outer<String>.Inner1A("Another");


Console.WriteLine(inst2);

var inst3 = new Outer<String>.Inner1B<int>("That", 2);


Console.WriteLine(inst3);
}
}
// The example displays the following output:
// Outer`1[System.String]
// Outer`1+Inner1A[System.String]
// Outer`1+Inner1B`1[System.String,System.Int32]
<Assembly:CLSCompliant(True)>

Public Class Outer(Of T)


Dim value As T

Public Sub New(value As T)


Me.value = value
End Sub

Public Class Inner1A : Inherits Outer(Of T)


Public Sub New(value As T)
MyBase.New(value)
End Sub
End Class

Public Class Inner1B(Of U) : Inherits Outer(Of T)


Dim value2 As U

Public Sub New(value1 As T, value2 As U)


MyBase.New(value1)
Me.value2 = value2
End Sub
End Class
End Class

Public Module Example


Public Sub Main()
Dim inst1 As New Outer(Of String)("This")
Console.WriteLine(inst1)

Dim inst2 As New Outer(Of String).Inner1A("Another")


Console.WriteLine(inst2)

Dim inst3 As New Outer(Of String).Inner1B(Of Integer)("That", 2)


Console.WriteLine(inst3)
End Sub
End Module
' The example displays the following output:
' Outer`1[System.String]
' Outer`1+Inner1A[System.String]
' Outer`1+Inner1B`1[System.String,System.Int32]

Generic type names are encoded in the form name`n, where name is the type name, ` is a character literal, and n is
the number of parameters declared on the type, or, for nested generic types, the number of newly introduced type
parameters. This encoding of generic type names is primarily of interest to developers who use reflection to access
CLS-complaint generic types in a library.
If constraints are applied to a generic type, any types used as constraints must also be CLS-compliant. The
following example defines a class named BaseClass that is not CLS-compliant and a generic class named
BaseCollection whose type parameter must derive from BaseClass . But because BaseClass is not CLS-compliant,
the compiler emits a warning.
using System;

[assembly:CLSCompliant(true)]

[CLSCompliant(false)] public class BaseClass


{}

public class BaseCollection<T> where T : BaseClass


{}
// Attempting to compile the example displays the following output:
// warning CS3024: Constraint type 'BaseClass' is not CLS-compliant

<Assembly: CLSCompliant(True)>

<CLSCompliant(False)> Public Class BaseClass


End Class

Public Class BaseCollection(Of T As BaseClass)


End Class
' Attempting to compile the example displays the following output:
' warning BC40040: Generic parameter constraint type 'BaseClass' is not
' CLS-compliant.
'
' Public Class BaseCollection(Of T As BaseClass)
' ~~~~~~~~~

If a generic type is derived from a generic base type, it must redeclare any constraints so that it can guarantee that
constraints on the base type are also satisfied. The following example defines a Number<T> that can represent any
numeric type. It also defines a FloatingPoint<T> class that represents a floating point value. However, the source
code fails to compile, because it does not apply the constraint on Number<T> (that T must be a value type) to
FloatingPoint<T> .
using System;

[assembly:CLSCompliant(true)]

public class Number<T> where T : struct


{
// use Double as the underlying type, since its range is a superset of
// the ranges of all numeric types except BigInteger.
protected double number;

public Number(T value)


{
try {
this.number = Convert.ToDouble(value);
}
catch (OverflowException e) {
throw new ArgumentException("value is too large.", e);
}
catch (InvalidCastException e) {
throw new ArgumentException("The value parameter is not numeric.", e);
}
}

public T Add(T value)


{
return (T) Convert.ChangeType(number + Convert.ToDouble(value), typeof(T));
}

public T Subtract(T value)


{
return (T) Convert.ChangeType(number - Convert.ToDouble(value), typeof(T));
}
}

public class FloatingPoint<T> : Number<T>


{
public FloatingPoint(T number) : base(number)
{
if (typeof(float) == number.GetType() ||
typeof(double) == number.GetType() ||
typeof(decimal) == number.GetType())
this.number = Convert.ToDouble(number);
else
throw new ArgumentException("The number parameter is not a floating-point number.");
}
}
// The attempt to comple the example displays the following output:
// error CS0453: The type 'T' must be a non-nullable value type in
// order to use it as parameter 'T' in the generic type or method 'Number<T>'
<Assembly:CLSCompliant(True)>

Public Class Number(Of T As Structure)


' Use Double as the underlying type, since its range is a superset of
' the ranges of all numeric types except BigInteger.
Protected number As Double

Public Sub New(value As T)


Try
Me.number = Convert.ToDouble(value)
Catch e As OverflowException
Throw New ArgumentException("value is too large.", e)
Catch e As InvalidCastException
Throw New ArgumentException("The value parameter is not numeric.", e)
End Try
End Sub

Public Function Add(value As T) As T


Return CType(Convert.ChangeType(number + Convert.ToDouble(value), GetType(T)), T)
End Function

Public Function Subtract(value As T) As T


Return CType(Convert.ChangeType(number - Convert.ToDouble(value), GetType(T)), T)
End Function
End Class

Public Class FloatingPoint(Of T) : Inherits Number(Of T)


Public Sub New(number As T)
MyBase.New(number)
If TypeOf number Is Single Or
TypeOf number Is Double Or
TypeOf number Is Decimal Then
Me.number = Convert.ToDouble(number)
Else
throw new ArgumentException("The number parameter is not a floating-point number.")
End If
End Sub
End Class
' The attempt to comple the example displays the following output:
' error BC32105: Type argument 'T' does not satisfy the 'Structure'
' constraint for type parameter 'T'.
'
' Public Class FloatingPoint(Of T) : Inherits Number(Of T)
' ~

The example compiles successfully if the constraint is added to the FloatingPoint<T> class.
using System;

[assembly:CLSCompliant(true)]

public class Number<T> where T : struct


{
// use Double as the underlying type, since its range is a superset of
// the ranges of all numeric types except BigInteger.
protected double number;

public Number(T value)


{
try {
this.number = Convert.ToDouble(value);
}
catch (OverflowException e) {
throw new ArgumentException("value is too large.", e);
}
catch (InvalidCastException e) {
throw new ArgumentException("The value parameter is not numeric.", e);
}
}

public T Add(T value)


{
return (T) Convert.ChangeType(number + Convert.ToDouble(value), typeof(T));
}

public T Subtract(T value)


{
return (T) Convert.ChangeType(number - Convert.ToDouble(value), typeof(T));
}
}

public class FloatingPoint<T> : Number<T> where T : struct


{
public FloatingPoint(T number) : base(number)
{
if (typeof(float) == number.GetType() ||
typeof(double) == number.GetType() ||
typeof(decimal) == number.GetType())
this.number = Convert.ToDouble(number);
else
throw new ArgumentException("The number parameter is not a floating-point number.");
}
}
<Assembly:CLSCompliant(True)>

Public Class Number(Of T As Structure)


' Use Double as the underlying type, since its range is a superset of
' the ranges of all numeric types except BigInteger.
Protected number As Double

Public Sub New(value As T)


Try
Me.number = Convert.ToDouble(value)
Catch e As OverflowException
Throw New ArgumentException("value is too large.", e)
Catch e As InvalidCastException
Throw New ArgumentException("The value parameter is not numeric.", e)
End Try
End Sub

Public Function Add(value As T) As T


Return CType(Convert.ChangeType(number + Convert.ToDouble(value), GetType(T)), T)
End Function

Public Function Subtract(value As T) As T


Return CType(Convert.ChangeType(number - Convert.ToDouble(value), GetType(T)), T)
End Function
End Class

Public Class FloatingPoint(Of T As Structure) : Inherits Number(Of T)


Public Sub New(number As T)
MyBase.New(number)
If TypeOf number Is Single Or
TypeOf number Is Double Or
TypeOf number Is Decimal Then
Me.number = Convert.ToDouble(number)
Else
throw new ArgumentException("The number parameter is not a floating-point number.")
End If
End Sub
End Class

The Common Language Specification imposes a conservative per-instantiation model for nested types and
protected members. Open generic types cannot expose fields or members with signatures that contain a specific
instantiation of a nested, protected generic type. Non-generic types that extend a specific instantiation of a generic
base class or interface cannot expose fields or members with signatures that contain a different instantiation of a
nested, protected generic type.
The following example defines a generic type, C1<T> (or C1(Of T) in Visual Basic), and a protected class, C1<T>.N
(or C1(Of T).N in Visual Basic). C1<T> has two methods, M1 and M2 . However, M1 is not CLS-compliant
because it tries to return a C1<int>.N (or C1(Of Integer).N ) object from C1<T> (or C1(Of T) ). A second class,
C2 , is derived from C1<long> (or C1(Of Long) ). It has two methods, M3 and M4 . M3 is not CLS-compliant
because it tries to return a C1<int>.N (or C1(Of Integer).N ) object from a subclass of C1<long> . Note that
language compilers can be even more restrictive. In this example, Visual Basic displays an error when it tries to
compile M4 .
using System;

[assembly:CLSCompliant(true)]

public class C1<T>


{
protected class N { }

protected void M1(C1<int>.N n) { } // Not CLS-compliant - C1<int>.N not


// accessible from within C1<T> in all
// languages
protected void M2(C1<T>.N n) { } // CLS-compliant – C1<T>.N accessible
// inside C1<T>
}

public class C2 : C1<long>


{
protected void M3(C1<int>.N n) { } // Not CLS-compliant – C1<int>.N is not
// accessible in C2 (extends C1<long>)

protected void M4(C1<long>.N n) { } // CLS-compliant, C1<long>.N is


// accessible in C2 (extends C1<long>)
}
// Attempting to compile the example displays output like the following:
// Generics4.cs(9,22): warning CS3001: Argument type 'C1<int>.N' is not CLS-compliant
// Generics4.cs(18,22): warning CS3001: Argument type 'C1<int>.N' is not CLS-compliant
<Assembly:CLSCompliant(True)>

Public Class C1(Of T)


Protected Class N
End Class

Protected Sub M1(n As C1(Of Integer).N) ' Not CLS-compliant - C1<int>.N not
' accessible from within C1(Of T) in all
End Sub ' languages

Protected Sub M2(n As C1(Of T).N) ' CLS-compliant – C1(Of T).N accessible
End Sub ' inside C1(Of T)
End Class

Public Class C2 : Inherits C1(Of Long)


Protected Sub M3(n As C1(Of Integer).N) ' Not CLS-compliant – C1(Of Integer).N is not
End Sub ' accessible in C2 (extends C1(Of Long))

Protected Sub M4(n As C1(Of Long).N)


End Sub
End Class
' Attempting to compile the example displays output like the following:
' error BC30508: 'n' cannot expose type 'C1(Of Integer).N' in namespace
' '<Default>' through class 'C1'.
'
' Protected Sub M1(n As C1(Of Integer).N) ' Not CLS-compliant - C1<int>.N not
' ~~~~~~~~~~~~~~~~
' error BC30389: 'C1(Of T).N' is not accessible in this context because
' it is 'Protected'.
'
' Protected Sub M3(n As C1(Of Integer).N) ' Not CLS-compliant - C1(Of Integer).N is not
'
' ~~~~~~~~~~~~~~~~
'
' error BC30389: 'C1(Of T).N' is not accessible in this context because it is 'Protected'.
'
' Protected Sub M4(n As C1(Of Long).N)
' ~~~~~~~~~~~~~

Constructors
Constructors in CLS-compliant classes and structures must follow these rules:
A constructor of a derived class must call the instance constructor of its base class before it accesses
inherited instance data. This requirement is due to the fact that base class constructors are not inherited by
their derived classes. This rule does not apply to structures, which do not support direct inheritance.
Typically, compilers enforce this rule independently of CLS compliance, as the following example shows. It
creates a Doctor class that is derived from a Person class, but the Doctor class fails to call the Person
class constructor to initialize inherited instance fields.
using System;

[assembly: CLSCompliant(true)]

public class Person


{
private string fName, lName, _id;

public Person(string firstName, string lastName, string id)


{
if (String.IsNullOrEmpty(firstName + lastName))
throw new ArgumentNullException("Either a first name or a last name must be provided.");

fName = firstName;
lName = lastName;
_id = id;
}

public string FirstName


{
get { return fName; }
}

public string LastName


{
get { return lName; }
}

public string Id
{
get { return _id; }
}

public override string ToString()


{
return String.Format("{0}{1}{2}", fName,
String.IsNullOrEmpty(fName) ? "" : " ",
lName);
}
}

public class Doctor : Person


{
public Doctor(string firstName, string lastName, string id)
{
}

public override string ToString()


{
return "Dr. " + base.ToString();
}
}
// Attempting to compile the example displays output like the following:
// ctor1.cs(45,11): error CS1729: 'Person' does not contain a constructor that takes 0
// arguments
// ctor1.cs(10,11): (Location of symbol related to previous error)
<Assembly: CLSCompliant(True)>

Public Class Person


Private fName, lName, _id As String

Public Sub New(firstName As String, lastName As String, id As String)


If String.IsNullOrEmpty(firstName + lastName) Then
Throw New ArgumentNullException("Either a first name or a last name must be provided.")
End If

fName = firstName
lName = lastName
_id = id
End Sub

Public ReadOnly Property FirstName As String


Get
Return fName
End Get
End Property

Public ReadOnly Property LastName As String


Get
Return lName
End Get
End Property

Public ReadOnly Property Id As String


Get
Return _id
End Get
End Property

Public Overrides Function ToString() As String


Return String.Format("{0}{1}{2}", fName,
If(String.IsNullOrEmpty(fName), "", " "),
lName)
End Function
End Class

Public Class Doctor : Inherits Person


Public Sub New(firstName As String, lastName As String, id As String)
End Sub

Public Overrides Function ToString() As String


Return "Dr. " + MyBase.ToString()
End Function
End Class
' Attempting to compile the example displays output like the following:
' Ctor1.vb(46) : error BC30148: First statement of this 'Sub New' must be a call
' to 'MyBase.New' or 'MyClass.New' because base class 'Person' of 'Doctor' does
' not have an accessible 'Sub New' that can be called with no arguments.
'
' Public Sub New()
' ~~~

An object constructor cannot be called except to create an object. In addition, an object cannot be initialized
twice. For example, this means that System.Object.MemberwiseClone and deserialization methods such as
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize must not call constructors.
Properties
Properties in CLS-compliant types must follow these rules:
A property must have a setter, a getter, or both. In an assembly, these are implemented as special methods,
which means that they will appear as separate methods (the getter is named get_ propertyname and the
setter is set_ propertyname) marked as SpecialName in the assembly's metadata. The C# and Visual Basic
compilers enforce this rule automatically without the need to apply the CLSCompliantAttribute attribute.
A property's type is the return type of the property getter and the last argument of the setter. These types
must be CLS compliant, and arguments cannot be assigned to the property by reference (that is, they
cannot be managed pointers).
If a property has both a getter and a setter, they must both be virtual, both static, or both instance. The C#
and Visual Basic compilers automatically enforce this rule through their property definition syntax.
Events
An event is defined by its name and its type. The event type is a delegate that is used to indicate the event. For
example, the System.AppDomain.AssemblyResolve event is of type ResolveEventHandler. In addition to the event
itself, three methods with names based on the event name provide the event's implementation and are marked as
SpecialName in the assembly's metadata:

A method for adding an event handler, named add_ EventName. For example, the event subscription
method for the System.AppDomain.AssemblyResolve event is named add_AssemblyResolve .
A method for removing an event handler, named remove_ EventName. For example, the removal method
for the System.AppDomain.AssemblyResolve event is named remove_AssemblyResolve .
A method for indicating that the event has occurred, named raise_ EventName.

NOTE
Most of the Common Language Specification's rules regarding events are implemented by language compilers and are
transparent to component developers.

The methods for adding, removing, and raising the event must have the same accessibility. They must also all be
static, instance, or virtual. The methods for adding and removing an event have one parameter whose type is the
event delegate type. The add and remove methods must both be present or both be absent.
The following example defines a CLS-compliant class named Temperature that raises a TemperatureChanged event
if the change in temperature between two readings equals or exceeds a threshold value. The Temperature class
explicitly defines a raise_TemperatureChanged method so that it can selectively execute event handlers.

using System;
using System.Collections;
using System.Collections.Generic;

[assembly: CLSCompliant(true)]

public class TemperatureChangedEventArgs : EventArgs


{
private Decimal originalTemp;
private Decimal newTemp;
private DateTimeOffset when;

public TemperatureChangedEventArgs(Decimal original, Decimal @new, DateTimeOffset time)


{
originalTemp = original;
newTemp = @new;
when = time;
}

public Decimal OldTemperature


{
get { return originalTemp; }
}
}

public Decimal CurrentTemperature


{
get { return newTemp; }
}

public DateTimeOffset Time


{
get { return when; }
}
}

public delegate void TemperatureChanged(Object sender, TemperatureChangedEventArgs e);

public class Temperature


{
private struct TemperatureInfo
{
public Decimal Temperature;
public DateTimeOffset Recorded;
}

public event TemperatureChanged TemperatureChanged;

private Decimal previous;


private Decimal current;
private Decimal tolerance;
private List<TemperatureInfo> tis = new List<TemperatureInfo>();

public Temperature(Decimal temperature, Decimal tolerance)


{
current = temperature;
TemperatureInfo ti = new TemperatureInfo();
ti.Temperature = temperature;
tis.Add(ti);
ti.Recorded = DateTimeOffset.UtcNow;
this.tolerance = tolerance;
}

public Decimal CurrentTemperature


{
get { return current; }
set {
TemperatureInfo ti = new TemperatureInfo();
ti.Temperature = value;
ti.Recorded = DateTimeOffset.UtcNow;
previous = current;
current = value;
if (Math.Abs(current - previous) >= tolerance)
raise_TemperatureChanged(new TemperatureChangedEventArgs(previous, current, ti.Recorded));
}
}

public void raise_TemperatureChanged(TemperatureChangedEventArgs eventArgs)


{
if (TemperatureChanged == null)
return;

foreach (TemperatureChanged d in TemperatureChanged.GetInvocationList()) {


if (d.Method.Name.Contains("Duplicate"))
Console.WriteLine("Duplicate event handler; event handler not executed.");
else
d.Invoke(this, eventArgs);
}
}
}

public class Example


{
{
public Temperature temp;

public static void Main()


{
Example ex = new Example();
}

public Example()
{
temp = new Temperature(65, 3);
temp.TemperatureChanged += this.TemperatureNotification;
RecordTemperatures();
Example ex = new Example(temp);
ex.RecordTemperatures();
}

public Example(Temperature t)
{
temp = t;
RecordTemperatures();
}

public void RecordTemperatures()


{
temp.TemperatureChanged += this.DuplicateTemperatureNotification;
temp.CurrentTemperature = 66;
temp.CurrentTemperature = 63;
}

internal void TemperatureNotification(Object sender, TemperatureChangedEventArgs e)


{
Console.WriteLine("Notification 1: The temperature changed from {0} to {1}", e.OldTemperature,
e.CurrentTemperature);
}

public void DuplicateTemperatureNotification(Object sender, TemperatureChangedEventArgs e)


{
Console.WriteLine("Notification 2: The temperature changed from {0} to {1}", e.OldTemperature,
e.CurrentTemperature);
}
}

Imports System.Collections
Imports System.Collections.Generic

<Assembly: CLSCompliant(True)>

Public Class TemperatureChangedEventArgs : Inherits EventArgs


Private originalTemp As Decimal
Private newTemp As Decimal
Private [when] As DateTimeOffset

Public Sub New(original As Decimal, [new] As Decimal, [time] As DateTimeOffset)


originalTemp = original
newTemp = [new]
[when] = [time]
End Sub

Public ReadOnly Property OldTemperature As Decimal


Get
Return originalTemp
End Get
End Property

Public ReadOnly Property CurrentTemperature As Decimal


Get
Return newTemp
Return newTemp
End Get
End Property

Public ReadOnly Property [Time] As DateTimeOffset


Get
Return [when]
End Get
End Property
End Class

Public Delegate Sub TemperatureChanged(sender As Object, e As TemperatureChangedEventArgs)

Public Class Temperature


Private Structure TemperatureInfo
Dim Temperature As Decimal
Dim Recorded As DateTimeOffset
End Structure

Public Event TemperatureChanged As TemperatureChanged

Private previous As Decimal


Private current As Decimal
Private tolerance As Decimal
Private tis As New List(Of TemperatureInfo)

Public Sub New(temperature As Decimal, tolerance As Decimal)


current = temperature
Dim ti As New TemperatureInfo()
ti.Temperature = temperature
ti.Recorded = DateTimeOffset.UtcNow
tis.Add(ti)
Me.tolerance = tolerance
End Sub

Public Property CurrentTemperature As Decimal


Get
Return current
End Get
Set
Dim ti As New TemperatureInfo
ti.Temperature = value
ti.Recorded = DateTimeOffset.UtcNow
previous = current
current = value
If Math.Abs(current - previous) >= tolerance Then
raise_TemperatureChanged(New TemperatureChangedEventArgs(previous, current, ti.Recorded))
End If
End Set
End Property

Public Sub raise_TemperatureChanged(eventArgs As TemperatureChangedEventArgs)


If TemperatureChangedEvent Is Nothing Then Exit Sub

Dim ListenerList() As System.Delegate = TemperatureChangedEvent.GetInvocationList()


For Each d As TemperatureChanged In TemperatureChangedEvent.GetInvocationList()
If d.Method.Name.Contains("Duplicate") Then
Console.WriteLine("Duplicate event handler; event handler not executed.")
Else
d.Invoke(Me, eventArgs)
End If
Next
End Sub
End Class

Public Class Example


Public WithEvents temp As Temperature

Public Shared Sub Main()


Dim ex As New Example()
Dim ex As New Example()
End Sub

Public Sub New()


temp = New Temperature(65, 3)
RecordTemperatures()
Dim ex As New Example(temp)
ex.RecordTemperatures()
End Sub

Public Sub New(t As Temperature)


temp = t
RecordTemperatures()
End Sub

Public Sub RecordTemperatures()


temp.CurrentTemperature = 66
temp.CurrentTemperature = 63

End Sub

Friend Shared Sub TemperatureNotification(sender As Object, e As TemperatureChangedEventArgs) _


Handles temp.TemperatureChanged
Console.WriteLine("Notification 1: The temperature changed from {0} to {1}", e.OldTemperature,
e.CurrentTemperature)
End Sub

Friend Shared Sub DuplicateTemperatureNotification(sender As Object, e As TemperatureChangedEventArgs) _


Handles temp.TemperatureChanged
Console.WriteLine("Notification 2: The temperature changed from {0} to {1}", e.OldTemperature,
e.CurrentTemperature)
End Sub
End Class

Overloads
The Common Language Specification imposes the following requirements on overloaded members:
Members can be overloaded based on the number of parameters and the type of any parameter. Calling
convention, return type, custom modifiers applied to the method or its parameter, and whether parameters
are passed by value or by reference are not considered when differentiating between overloads. For an
example, see the code for the requirement that names must be unique within a scope in the Naming
conventions section.
Only properties and methods can be overloaded. Fields and events cannot be overloaded.
Generic methods can be overloaded based on the number of their generic parameters.

NOTE
The op_Explicit and op_Implicit operators are exceptions to the rule that return value is not considered part of a
method signature for overload resolution. These two operators can be overloaded based on both their parameters and their
return value.

Exceptions
Exception objects must derive from System.Exception or from another type derived from System.Exception. The
following example illustrates the compiler error that results when a custom class named ErrorClass is used for
exception handling.
using System;

[assembly: CLSCompliant(true)]

public class ErrorClass


{
string msg;

public ErrorClass(string errorMessage)


{
msg = errorMessage;
}

public string Message


{
get { return msg; }
}
}

public static class StringUtilities


{
public static string[] SplitString(this string value, int index)
{
if (index < 0 | index > value.Length) {
ErrorClass badIndex = new ErrorClass("The index is not within the string.");
throw badIndex;
}
string[] retVal = { value.Substring(0, index - 1),
value.Substring(index) };
return retVal;
}
}
// Compilation produces a compiler error like the following:
// Exceptions1.cs(26,16): error CS0155: The type caught or thrown must be derived from
// System.Exception
Imports System.Runtime.CompilerServices

<Assembly: CLSCompliant(True)>

Public Class ErrorClass


Dim msg As String

Public Sub New(errorMessage As String)


msg = errorMessage
End Sub

Public ReadOnly Property Message As String


Get
Return msg
End Get
End Property
End Class

Public Module StringUtilities


<Extension()> Public Function SplitString(value As String, index As Integer) As String()
If index < 0 Or index > value.Length Then
Dim BadIndex As New ErrorClass("The index is not within the string.")
Throw BadIndex
End If
Dim retVal() As String = { value.Substring(0, index - 1),
value.Substring(index) }
Return retVal
End Function
End Module
' Compilation produces a compiler error like the following:
' Exceptions1.vb(27) : error BC30665: 'Throw' operand must derive from 'System.Exception'.
'
' Throw BadIndex
' ~~~~~~~~~~~~~~

To correct this error, the ErrorClass class must inherit from System.Exception. In addition, the Message property
must be overridden. The following example corrects these errors to define an ErrorClass class that is CLS-
compliant.
using System;

[assembly: CLSCompliant(true)]

public class ErrorClass : Exception


{
string msg;

public ErrorClass(string errorMessage)


{
msg = errorMessage;
}

public override string Message


{
get { return msg; }
}
}

public static class StringUtilities


{
public static string[] SplitString(this string value, int index)
{
if (index < 0 | index > value.Length) {
ErrorClass badIndex = new ErrorClass("The index is not within the string.");
throw badIndex;
}
string[] retVal = { value.Substring(0, index - 1),
value.Substring(index) };
return retVal;
}
}

Imports System.Runtime.CompilerServices

<Assembly: CLSCompliant(True)>

Public Class ErrorClass : Inherits Exception


Dim msg As String

Public Sub New(errorMessage As String)


msg = errorMessage
End Sub

Public Overrides ReadOnly Property Message As String


Get
Return msg
End Get
End Property
End Class

Public Module StringUtilities


<Extension()> Public Function SplitString(value As String, index As Integer) As String()
If index < 0 Or index > value.Length Then
Dim BadIndex As New ErrorClass("The index is not within the string.")
Throw BadIndex
End If
Dim retVal() As String = { value.Substring(0, index - 1),
value.Substring(index) }
Return retVal
End Function
End Module

Attributes
In.NET Framework assemblies, custom attributes provide an extensible mechanism for storing custom attributes
and retrieving metadata about programming objects, such as assemblies, types, members, and method
parameters. Custom attributes must derive from System.Attribute or from a type derived from System.Attribute.
The following example violates this rule. It defines a NumericAttribute class that does not derive from
System.Attribute. Note that a compiler error results only when the non-CLS-compliant attribute is applied, not
when the class is defined.

using System;

[assembly: CLSCompliant(true)]

[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Struct)]
public class NumericAttribute
{
private bool _isNumeric;

public NumericAttribute(bool isNumeric)


{
_isNumeric = isNumeric;
}

public bool IsNumeric


{
get { return _isNumeric; }
}
}

[Numeric(true)] public struct UDouble


{
double Value;
}
// Compilation produces a compiler error like the following:
// Attribute1.cs(22,2): error CS0616: 'NumericAttribute' is not an attribute class
// Attribute1.cs(7,14): (Location of symbol related to previous error)

<Assembly: CLSCompliant(True)>

<AttributeUsageAttribute(AttributeTargets.Class Or AttributeTargets.Struct)> _
Public Class NumericAttribute
Private _isNumeric As Boolean

Public Sub New(isNumeric As Boolean)


_isNumeric = isNumeric
End Sub

Public ReadOnly Property IsNumeric As Boolean


Get
Return _isNumeric
End Get
End Property
End Class

<Numeric(True)> Public Structure UDouble


Dim Value As Double
End Structure
' Compilation produces a compiler error like the following:
' error BC31504: 'NumericAttribute' cannot be used as an attribute because it
' does not inherit from 'System.Attribute'.
'
' <Numeric(True)> Public Structure UDouble
' ~~~~~~~~~~~~~
The constructor or the properties of a CLS-compliant attribute can expose only the following types:
Boolean
Byte
Char
Double
Int16
Int32
Int64
Single
String
Type
Any enumeration type whose underlying type is Byte, Int16, Int32, or Int64.
The following example defines a DescriptionAttribute class that derives from Attribute. The class constructor has
a parameter of type Descriptor , so the class is not CLS-compliant. Note that the C# compiler emits a warning but
compiles successfully, whereas the Visual Basic compiler emits neither a warning nor an error.

using System;

[assembly:CLSCompliantAttribute(true)]

public enum DescriptorType { type, member };

public class Descriptor


{
public DescriptorType Type;
public String Description;
}

[AttributeUsage(AttributeTargets.All)]
public class DescriptionAttribute : Attribute
{
private Descriptor desc;

public DescriptionAttribute(Descriptor d)
{
desc = d;
}

public Descriptor Descriptor


{ get { return desc; } }
}
// Attempting to compile the example displays output like the following:
// warning CS3015: 'DescriptionAttribute' has no accessible
// constructors which use only CLS-compliant types
<Assembly:CLSCompliantAttribute(True)>

Public Enum DescriptorType As Integer


Type = 0
Member = 1
End Enum

Public Class Descriptor


Public Type As DescriptorType
Public Description As String
End Class

<AttributeUsage(AttributeTargets.All)> _
Public Class DescriptionAttribute : Inherits Attribute
Private desc As Descriptor

Public Sub New(d As Descriptor)


desc = d
End Sub

Public ReadOnly Property Descriptor As Descriptor


Get
Return desc
End Get
End Property
End Class

The CLSCompliantAttribute attribute


The CLSCompliantAttribute attribute is used to indicate whether a program element complies with the Common
Language Specification. The System.CLSCompliantAttribute.CLSCompliantAttribute(Boolean) constructor includes
a single required parameter, isCompliant , that indicates whether the program element is CLS-compliant.
At compile time, the compiler detects non-compliant elements that are presumed to be CLS-compliant and emits a
warning. The compiler does not emit warnings for types or members that are explicitly declared to be non-
compliant.
Component developers can use the CLSCompliantAttribute attribute in two ways:
To define the parts of the public interface exposed by a component that are CLS-compliant and the parts
that are not CLS-compliant. When the attribute is used to mark particular program elements as CLS-
compliant, its use guarantees that those elements are accessible from all languages and tools that target the
.NET Framework.
To ensure that the component library's public interface exposes only program elements that are CLS-
compliant. If elements are not CLS-compliant, compilers will generally issue a warning.

WARNING
In some cases, language compilers enforce CLS-compliant rules regardless of whether the CLSCompliantAttribute attribute is
used. For example, defining a static member in an interface violates a CLS rule. However, if you define a static (in C#) or
Shared (in Visual Basic) member in an interface, both the C# and Visual Basic compilers display an error message and fail to
compile the app.

The CLSCompliantAttribute attribute is marked with an AttributeUsageAttribute attribute that has a value of
System.AttributeTargets.All. This value allows you to apply the CLSCompliantAttribute attribute to any program
element, including assemblies, modules, types (classes, structures, enumerations, interfaces, and delegates), type
members (constructors, methods, properties, fields, and events), parameters, generic parameters, and return
values. However, in practice, you should apply the attribute only to assemblies, types, and type members.
Otherwise, compilers ignore the attribute and continue to generate compiler warnings whenever they encounter a
non-compliant parameter, generic parameter, or return value in your library's public interface.
The value of the CLSCompliantAttribute attribute is inherited by contained program elements. For example, if an
assembly is marked as CLS-compliant, its types are also CLS-compliant. If a type is marked as CLS-compliant, its
nested types and members are also CLS-compliant.
You can explicitly override the inherited compliance by applying the CLSCompliantAttribute attribute to a
contained program element. For example, you can use the CLSCompliantAttribute attribute with an isCompliant
value of false to define a non-compliant type in a compliant assembly, and you can use the attribute with an
isCompliant value of true to define a compliant type in a non-compliant assembly. You can also define non-
compliant members in a compliant type. However, a non-compliant type cannot have compliant members, so you
cannot use the attribute with an isCompliant value of true to override inheritance from a non-compliant type.
When you are developing components, you should always use the CLSCompliantAttribute attribute to indicate
whether your assembly, its types, and its members are CLS-compliant.
To create CLS-compliant components:
1. Use the CLSCompliantAttribute to mark you assembly as CLS-compliant.
2. Mark any publicly exposed types in the assembly that are not CLS-compliant as non-compliant.
3. Mark any publicly exposed members in CLS-compliant types as non-compliant.
4. Provide a CLS-compliant alternative for non-CLS-compliant members.
If you've successfully marked all your non-compliant types and members, your compiler should not emit any non-
compliance warnings. However, you should indicate which members are not CLS-compliant and list their CLS-
compliant alternatives in your product documentation.
The following example uses the CLSCompliantAttribute attribute to define a CLS-compliant assembly and a type,
CharacterUtilities , that has two non-CLS-compliant members. Because both members are tagged with the
CLSCompliant(false) attribute, the compiler produces no warnings. The class also provides a CLS-compliant
alternative for both methods. Ordinarily, we would just add two overloads to the ToUTF16 method to provide CLS-
compliant alternatives. However, because methods cannot be overloaded based on return value, the names of the
CLS-compliant methods are different from the names of the non-compliant methods.
using System;
using System.Text;

[assembly:CLSCompliant(true)]

public class CharacterUtilities


{
[CLSCompliant(false)] public static ushort ToUTF16(String s)
{
s = s.Normalize(NormalizationForm.FormC);
return Convert.ToUInt16(s[0]);
}

[CLSCompliant(false)] public static ushort ToUTF16(Char ch)


{
return Convert.ToUInt16(ch);
}

// CLS-compliant alternative for ToUTF16(String).


public static int ToUTF16CodeUnit(String s)
{
s = s.Normalize(NormalizationForm.FormC);
return (int) Convert.ToUInt16(s[0]);
}

// CLS-compliant alternative for ToUTF16(Char).


public static int ToUTF16CodeUnit(Char ch)
{
return Convert.ToInt32(ch);
}

public bool HasMultipleRepresentations(String s)


{
String s1 = s.Normalize(NormalizationForm.FormC);
return s.Equals(s1);
}

public int GetUnicodeCodePoint(Char ch)


{
if (Char.IsSurrogate(ch))
throw new ArgumentException("ch cannot be a high or low surrogate.");

return Char.ConvertToUtf32(ch.ToString(), 0);


}

public int GetUnicodeCodePoint(Char[] chars)


{
if (chars.Length > 2)
throw new ArgumentException("The array has too many characters.");

if (chars.Length == 2) {
if (! Char.IsSurrogatePair(chars[0], chars[1]))
throw new ArgumentException("The array must contain a low and a high surrogate.");
else
return Char.ConvertToUtf32(chars[0], chars[1]);
}
else {
return Char.ConvertToUtf32(chars.ToString(), 0);
}
}
}
Imports System.Text

<Assembly:CLSCompliant(True)>

Public Class CharacterUtilities


<CLSCompliant(False)> Public Shared Function ToUTF16(s As String) As UShort
s = s.Normalize(NormalizationForm.FormC)
Return Convert.ToUInt16(s(0))
End Function

<CLSCompliant(False)> Public Shared Function ToUTF16(ch As Char) As UShort


Return Convert.ToUInt16(ch)
End Function

' CLS-compliant alternative for ToUTF16(String).


Public Shared Function ToUTF16CodeUnit(s As String) As Integer
s = s.Normalize(NormalizationForm.FormC)
Return CInt(Convert.ToInt16(s(0)))
End Function

' CLS-compliant alternative for ToUTF16(Char).


Public Shared Function ToUTF16CodeUnit(ch As Char) As Integer
Return Convert.ToInt32(ch)
End Function

Public Function HasMultipleRepresentations(s As String) As Boolean


Dim s1 As String = s.Normalize(NormalizationForm.FormC)
Return s.Equals(s1)
End Function

Public Function GetUnicodeCodePoint(ch As Char) As Integer


If Char.IsSurrogate(ch) Then
Throw New ArgumentException("ch cannot be a high or low surrogate.")
End If
Return Char.ConvertToUtf32(ch.ToString(), 0)
End Function

Public Function GetUnicodeCodePoint(chars() As Char) As Integer


If chars.Length > 2 Then
Throw New ArgumentException("The array has too many characters.")
End If
If chars.Length = 2 Then
If Not Char.IsSurrogatePair(chars(0), chars(1)) Then
Throw New ArgumentException("The array must contain a low and a high surrogate.")
Else
Return Char.ConvertToUtf32(chars(0), chars(1))
End If
Else
Return Char.ConvertToUtf32(chars.ToString(), 0)
End If
End Function
End Class

If you are developing an app rather than a library (that is, if you aren't exposing types or members that can be
consumed by other app developers), the CLS compliance of the program elements that your app consumes are of
interest only if your language does not support them. In that case, your language compiler will generate an error
when you try to use a non-CLS-compliant element.

Cross-Language Interoperability
Language independence has a number of possible meanings. One meaning, which is discussed in the article
Language Independence and Language-Independent Components, involves seamlessly consuming types written in
one language from an app written in another language. A second meaning, which is the focus of this article,
involves combining code written in multiple languages into a single .NET Framework assembly.
The following example illustrates cross-language interoperability by creating a class library named Utilities.dll that
includes two classes, NumericLib and StringLib . The NumericLib class is written in C#, and the StringLib class is
written in Visual Basic. Here's the source code for StringUtil.vb, which includes a single member, ToTitleCase , in
its StringLib class.

Imports System.Collections.Generic
Imports System.Runtime.CompilerServices

Public Module StringLib


Private exclusions As List(Of String)

Sub New()
Dim words() As String = { "a", "an", "and", "of", "the" }
exclusions = New List(Of String)
exclusions.AddRange(words)
End Sub

<Extension()> _
Public Function ToTitleCase(title As String) As String
Dim words() As String = title.Split()
Dim result As String = String.Empty

For ctr As Integer = 0 To words.Length - 1


Dim word As String = words(ctr)
If ctr = 0 OrElse Not exclusions.Contains(word.ToLower()) Then
result += word.Substring(0, 1).ToUpper() + _
word.Substring(1).ToLower()
Else
result += word.ToLower()
End If
If ctr <= words.Length - 1 Then
result += " "
End If
Next
Return result
End Function
End Module

Here's the source code for NumberUtil.cs, which defines a NumericLib class that has two members, IsEven and
NearZero .
using System;

public static class NumericLib


{
public static bool IsEven(this IConvertible number)
{
if (number is Byte ||
number is SByte ||
number is Int16 ||
number is UInt16 ||
number is Int32 ||
number is UInt32 ||
number is Int64)
return Convert.ToInt64(number) % 2 == 0;
else if (number is UInt64)
return ((ulong) number) % 2 == 0;
else
throw new NotSupportedException("IsEven called for a non-integer value.");
}

public static bool NearZero(double number)


{
return Math.Abs(number) < .00001;
}
}

To package the two classes in a single assembly, you must compile them into modules. To compile the Visual Basic
source code file into a module, use this command:

vbc /t:module StringUtil.vb

For more information about the command-line syntax of the Visual Basic compiler, see Building from the
Command Line.
To compile the C# source code file into a module, use this command:

csc /t:module NumberUtil.cs

For more information about the command-line syntax of the C# compiler, see Command-line Building With
csc.exe.
You then use the Link tool (Link.exe) to compile the two modules into an assembly:

link numberutil.netmodule stringutil.netmodule /out:UtilityLib.dll /dll

The following example then calls the NumericLib.NearZero and StringLib.ToTitleCase methods. Note that both the
Visual Basic code and the C# code are able to access the methods in both classes.
using System;

public class Example


{
public static void Main()
{
Double dbl = 0.0 - Double.Epsilon;
Console.WriteLine(NumericLib.NearZero(dbl));

string s = "war and peace";


Console.WriteLine(s.ToTitleCase());
}
}
// The example displays the following output:
// True
// War and Peace

Module Example
Public Sub Main()
Dim dbl As Double = 0.0 - Double.Epsilon
Console.WriteLine(NumericLib.NearZero(dbl))

Dim s As String = "war and peace"


Console.WriteLine(s.ToTitleCase())
End Sub
End Module
' The example displays the following output:
' True
' War and Peace

To compile the Visual Basic code, use this command:

vbc example.vb /r:UtilityLib.dll

To compile with C#, change the name of the compiler from vbc to csc, and change the file extension from .vb to
.cs:

csc example.cs /r:UtilityLib.dll

See Also
CLSCompliantAttribute
Framework Libraries
8/10/2017 • 2 min to read • Edit Online

.NET has an expansive standard set of class libraries, referred to as either the base class libraries (core set) or
framework class libraries (complete set). These libraries provide implementations for many general and app-
specific types, algorithms and utility functionality. Both commercial and community libraries build on top of the
framework class libraries, providing easy to use off-the-shelf libraries for a wide set of computing tasks.
A subset of these libraries are provided with each .NET implementation. Base Class Library (BCL) APIs are expected
with any .NET implementation, both because developers will want them and because popular libraries will need
them to run. App-specific libraries above the BCL, such as ASP.NET, will not be available on all .NET
implementations.

Base Class Libraries


The BCL provides the most foundational types and utility functionality and are the base of all other .NET class
libraries. They aim to provide very general implementations without any bias to any workload. Performance is
always an important consideration, since apps might prefer a particular policy, such as low-latency to high-
throughput or low-memory to low-CPU usage. These libraries are intended to be high-performance generally, and
take a middle-ground approach according to these various performance concerns. For most apps, this approach
has been quite successful.

Primitive Types
.NET includes a set of primitive types, which are used (to varying degrees) in all programs. These types contain
data, such as numbers, strings, bytes and arbitrary objects. The C# language includes keywords for these types. A
sample set of these types is listed below, with the matching C# keywords.
System.Object (object) - The ultimate base class in the CLR type system. It is the root of the type hierarchy.
System.Int16 (short) - A 16-bit signed integer type. The unsigned UInt16 also exists.
System.Int32 (int) - A 32-bit signed integer type. The unsigned UInt32 also exists.
System.Single (float) - A 32-bit floating-point type.
System.Decimal (decimal) - A 128-bit decimal type.
System.Byte (byte) - An unsigned 8-bit integer that represents a byte of memory.
System.Boolean (bool) - A boolean type that represents true or false .
System.Char (char) - A 16-bit numeric type that represents a Unicode character.
System.String (string) - Represents a series of characters. Different than a char[] , but enables indexing into
each individual char in the string .

Data Structures
.NET includes a set of data structures that are the workhorses of almost any .NET apps. These are mostly collections,
but also include other types.
Array - Represents an array of strongly types objects that can be accessed by index. Has a fixed size, per its
construction.
List<T> - Represents a strongly typed list of objects that can be accessed by index. Is automatically resized as
needed.
Dictionary<TKey,TValue> - Represents a collection of values that are indexed by a key. Values can be accessed
via key. Is automatically resized as needed.
Uri - Provides an object representation of a uniform resource identifier (URI) and easy access to the parts of the
URI.
DateTime - Represents an instant in time, typically expressed as a date and time of day.

Utility APIs
.NET includes a set of utility APIs that provide functionality for many important tasks.
HttpClient - An API for sending HTTP requests and receiving HTTP responses from a resource identified by a
URI.
XDocument - An API for loading, and querying XML documents with LINQ.
StreamReader - An API for reading files (StringWriter) Can be used to write files.

App-Model APIs
There are many app-models that can be used with .NET, provided by several companies.
ASP.NET - Provides a web framework for building Web sites and services. Supported on Windows, Linux and
macOS (depends on ASP.NET version).
.NET Framework Class Library Overview
7/29/2017 • 4 min to read • Edit Online

The .NET Framework includes classes, interfaces, and value types that expedite and optimize the development
process and provide access to system functionality. To facilitate interoperability between languages, most .NET
Framework types are CLS-compliant and can therefore be used from any programming language whose compiler
conforms to the common language specification (CLS).
The .NET Framework types are the foundation on which .NET applications, components, and controls are built. The
.NET Framework includes types that perform the following functions:
Represent base data types and exceptions.
Encapsulate data structures.
Perform I/O.
Access information about loaded types.
Invoke .NET Framework security checks.
Provide data access, rich client-side GUI, and server-controlled, client-side GUI.
The .NET Framework provides a rich set of interfaces, as well as abstract and concrete (non-abstract) classes. You
can use the concrete classes as is or, in many cases, derive your own classes from them. To use the functionality of
an interface, you can either create a class that implements the interface or derive a class from one of the .NET
Framework classes that implements the interface.

Naming Conventions
.NET Framework types use a dot syntax naming scheme that connotes a hierarchy. This technique groups related
types into namespaces so they can be searched and referenced more easily. The first part of the full name — up to
the rightmost dot — is the namespace name. The last part of the name is the type name. For example,
System.Collections.ArrayList represents the ArrayList type, which belongs to the System.Collections
namespace. The types in System.Collections can be used to manipulate collections of objects.
This naming scheme makes it easy for library developers extending the .NET Framework to create hierarchical
groups of types and name them in a consistent, informative manner. It also allows types to be unambiguously
identified by their full name (that is, by their namespace and type name), which prevents type name collisions.
Library developers are expected to use the following convention when creating names for their namespaces:
CompanyName.TechnologyName
For example, the namespace Microsoft.Word conforms to this guideline.
The use of naming patterns to group related types into namespaces is a very useful way to build and document
class libraries. However, this naming scheme has no effect on visibility, member access, inheritance, security, or
binding. A namespace can be partitioned across multiple assemblies and a single assembly can contain types from
multiple namespaces. The assembly provides the formal structure for versioning, deployment, security, loading, and
visibility in the common language runtime.
For more information on namespaces and type names, see Common Type System.

System Namespace
The System namespace is the root namespace for fundamental types in the .NET Framework. This namespace
includes classes that represent the base data types used by all applications: Object (the root of the inheritance
hierarchy), Byte, Char, Array, Int32, String, and so on. Many of these types correspond to the primitive data types
that your programming language uses. When you write code using .NET Framework types, you can use your
language's corresponding keyword when a .NET Framework base data type is expected.
The following table lists the base types that the .NET Framework supplies, briefly describes each type, and indicates
the corresponding type in Visual Basic, C#, C++, and JScript.

VISUAL BASIC JSCRIPT DATA


CATEGORY CLASS NAME DESCRIPTION DATA TYPE C# DATA TYPE C++ DATA TYPE TYPE

Integer Byte An 8-bit Byte byte unsigned Byte


unsigned char
integer.

SByte An 8-bit SByte sbyte char SByte


signed
integer. -or-

Not CLS- signed char


compliant.

Int16 A 16-bit Short short short short


signed
integer.

Int32 A 32-bit Integer int int int


signed
integer. -or-

long

Int64 A 64-bit Long long __int64 long


signed
integer.

UInt16 A 16-bit UShort ushort unsigned UInt16


unsigned short
integer.

Not CLS-
compliant.

UInt32 A 32-bit UInteger uint unsigned int UInt32


unsigned
integer. -or-

Not CLS- unsigned


compliant. long

UInt64 A 64-bit ULong ulong unsigned UInt64


unsigned __int64
integer.

Not CLS-
compliant.
VISUAL BASIC JSCRIPT DATA
CATEGORY CLASS NAME DESCRIPTION DATA TYPE C# DATA TYPE C++ DATA TYPE TYPE

Floating point Single A single- Single float float float


precision (32-
bit) floating-
point number.

Double A double- Double double double double


precision (64-
bit) floating-
point number.

Logical Boolean A Boolean Boolean bool bool bool


value (true or
false).

Other Char A Unicode Char char wchar_t char


(16-bit)
character.

Decimal A decimal Decimal decimal Decimal Decimal


(128-bit)
value.

IntPtr A signed IntPtr IntPtr IntPtr IntPtr


integer whose
size depends No built-in No built-in No built-in
on the type. type. type.
underlying
platform (a
32-bit value
on a 32-bit
platform and
a 64-bit value
on a 64-bit
platform).

UIntPtr An unsigned UIntPtr UIntPtr UIntPtr UIntPtr


integer whose
size depends No built-in No built-in No built-in
on the type. type. type.
underlying
platform (a
32- bit value
on a 32-bit
platform and
a 64-bit value
on a 64-bit
platform).

Not CLS-
compliant.

ass objects Object The root of Object object Object\* Object


the object
hierarchy.
VISUAL BASIC JSCRIPT DATA
CATEGORY CLASS NAME DESCRIPTION DATA TYPE C# DATA TYPE C++ DATA TYPE TYPE

String An immutable, String string String\* String


fixed-length
string of
Unicode
characters.

In addition to the base data types, the System namespace contains over 100 classes, ranging from classes that
handle exceptions to classes that deal with core runtime concepts, such as application domains and the garbage
collector. The System namespace also contains many second-level namespaces.
For more information about namespaces, browse the .NET Framework Class Library. The reference documentation
provides a brief overview of each namespace as well as a formal description of each type and its members.

See Also
Common Type System
.NET Framework Class Library
Overview
Working with Base Types in .NET
7/29/2017 • 1 min to read • Edit Online

This section describes .NET base type operations, including formatting, conversion, and common operations.

In This Section
Type Conversion in the .NET Framework
Describes how to convert from one type to another.
Formatting Types
Describes how to format strings using the string format specifiers.
Manipulating Strings
Describes how to manipulate and format strings.
Parsing Strings
Describes how to convert strings into .NET Framework types.

Related Sections
Common Type System
Describes types used by the .NET Framework.
Dates, Times, and Time Zones
Describes how to work with time zones and time zone conversions in time zone-aware applications.
.NET Class Libraries
8/5/2017 • 3 min to read • Edit Online

Class libraries are the shared library concept for .NET. They enable you to componentize useful functionality into
modules that can be used by multiple applications. They can also be used as a means of loading functionality that is
not needed or not known at application startup. Class libraries are described using the .NET Assembly file format.
There are three types of class libraries that you can use:
Platform-specific class libraries have access to all the APIs in a given platform (for example, .NET Framework,
Xamarin iOS), but can only be used by apps and libraries that target that platform.
Portable class libraries have access to a subset of APIs, and can be used by apps and libraries that target
multiple platforms.
.NET Core class libraries are a merger of the platform-specific and portable library concept into a single model
that provides the best of both.

Platform-specific Class Libraries


Platform-specific libraries are bound to a single .NET implementation (for example, .NET Framework on Windows)
and can therefore take significant dependencies on a known execution environment. Such an environment will
expose a known set of APIs (.NET and OS APIs) and will maintain and expose expected state (for example, Windows
registry).
Developers who create platform specific libraries can fully exploit the underlying platform. The libraries will only
ever run on that given platform, making platform checks or other forms of conditional code unnecessary (modulo
single sourcing code for multiple platforms).
Platform-specific libraries have been the primary class library type for the .NET Framework. Even as other .NET
implementations emerged, platform-specific libraries remained the dominant library type.

Portable Class Libraries


Portable libraries are supported on multiple .NET implementations. They can still take dependencies on a known
execution environment, however, the environment is a synthetic one that is generated by the intersection of a set of
concrete .NET implementations. This means that exposed APIs and platform assumptions are a subset of what
would be available to a platform-specific library.
You choose a platform configuration when you create a portable library. These are the set of platforms that you
need to support (for example, .NET Framework 4.5+, Windows Phone 8.0+). The more platforms you opt to
support, the fewer APIs and fewer platform assumptions you can make, the lowest common denominator. This
characteristic can be confusing at first, since people often think "more is better", but find that more supported
platforms results in fewer available APIs.
Many library developers have switched from producing multiple platform-specific libraries from one source (using
conditional compilation directives) to portable libraries. There are several approaches for accessing platform-
specific functionality within portable libraries, with bait-and-switch being the most widely accepted technique at
this point.
.NET Standard Class Libraries
.NET Standard libraries are a replacement of the platform-specific and portable libraries concepts. They are
platform-specific in the sense that they expose all functionality from the underlying platform (no synthetic
platforms or platform intersections). They are portable in the sense that they work on all supporting platforms.
The .NET Standard exposes a set of library contracts. .NET implementations must support each contract fully or not
at all. Each implementation, therefore, supports a set of .NET Standard contracts. The corollary is that each .NET
Standard class library is supported on the platforms that support it’s contract dependencies.
The .NET Standard does not expose the entire functionality of the .NET Framework (nor is that a goal), however,
they do expose many more APIs than Portable Class Libraries. More APIs will be added over time.
The following platforms support .NET Standard libraries:
.NET Core
ASP.NET Core
.NET Framework 4.5+
Windows Store Apps
Windows Phone 8+
Mono Class Libraries
Class libraries are supported on Mono, including the three types of libraries described above. Mono has often been
seen (correctly) as a cross-platform implementation of the Microsoft .NET Framework. In part, this was because
platform-specific .NET Framework libraries could run on the Mono runtime without modification or recompilation.
This characteristic was in place before the creation of portable class libraries, so was an obvious choice to enable
binary portability between the .NET Framework and Mono (although it only worked in one direction).
The .NET Portability Analyzer
8/5/2017 • 2 min to read • Edit Online

Want to make your libraries multi-platform? Want to see how much work is required to make your application
compatible with other .NET implementations? The .NET Portability Analyzer is a tool that provides you with a
detailed report on how flexible your program is across .NET implementations by analyzing assemblies. The
Portability Analyzer is offered as a Visual Studio Extension and as a console app.

New targets
.NET Core: Has a modular design, employs side-by-side, and targets cross-platform scenarios. Side-by-side
allows you to adopt new .NET Core versions without breaking other apps.
ASP.NET Core: is a modern web-framework built on .NET Core thus giving developers the same benefits.
Universal Windows Platform: Improve performance of your Windows Store apps that run on x64 and ARM
machines by using .NET Native’s static compilation.
.NET Core + Platform Extensions: Includes the .NET Core APIs in addition to other APIs in the .NET ecosystem
such as WCF, ASP.NET Core, FSharp, and Azure.
.NET Standard + Platform Extensions: Includes the .NET Standard APIs in addition to other .NET ecosystem such
as WCF, ASP.NET Core, FSharp, and Azure.

How to use Portability Analyzer


To begin using the .NET Portability Analyzer, you first need to download and install the extension from the Visual
Studio Gallery. It works on Visual Studio 2015 and Visual Studio 2017. You can configure it in Visual Studio via
Analyze > Portability Analyzer Settings and select your Target Platforms.
To analyze your entire project, right-click on your project in Solution Explorer and select Analyze Assembly
Portability. Otherwise, go to the Analyze menu and select Analyze Assembly Portability. From there, select
your project’s executable or DLL.

After running the analysis, you will see your .NET Portability Report. Only types that are unsupported by a target
platform appear in the list and you can review recommendations in the Messages tab in the Error List. You can
also jump to problem areas directly from the Messages tab.

Don’t want to use Visual Studio? You can also use the Portability Analyzer from the command prompt. Just
download the API Portability Analyzer.
Type the following command to analyze the current directory: \...\ApiPort.exe analyze -f .
To analyze a specific list of .dll files, type the following command:
\...\ApiPort.exe analyze -f first.dll -f second.dll -f third.dll

Your .NET Portability Report is saved as an Excel file (.xlsx) in your current directory. The Details tab in the Excel
Workbook contains more information.
For more information on the .NET Portability Analyzer, visit the GitHub documentation and A Brief Look at the .NET
Portability Analyzer Channel 9 video.
Handling and throwing exceptions in .NET
7/29/2017 • 2 min to read • Edit Online

Applications must be able to handle errors that occur during execution in a consistent manner. .NET provides a
model for notifying applications of errors in a uniform way: .NET operations indicate failure by throwing exceptions.

Exceptions
An exception is any error condition or unexpected behavior that is encountered by an executing program.
Exceptions can be thrown because of a fault in your code or in code that you call (such as a shared library),
unavailable operating system resources, unexpected conditions that the runtime encounters (such as code that
cannot be verified), and so on. Your application can recover from some of these conditions, but not from others.
Although you can recover from most application exceptions, you cannot recover from most runtime exceptions.
In .NET, an exception is an object that inherits from the System.Exception class. An exception is thrown from an area
of code where a problem has occurred. The exception is passed up the stack until the application handles it or the
program terminates.

Exceptions vs. traditional error-handling methods


Traditionally, a language's error-handling model relied on either the language's unique way of detecting errors and
locating handlers for them, or on the error-handling mechanism provided by the operating system. The way .NET
implements exception handling provides the following advantages:
Exception throwing and handling works the same for .NET programming languages.
Does not require any particular language syntax for handling exceptions, but allows each language to define
its own syntax.
Exceptions can be thrown across process and even machine boundaries.
Exception-handling code can be added to an application to increase program reliability.
Exceptions offer advantages over other methods of error notification, such as return codes. Failures do not go
unnoticed because if an exception is thrown and you don't handle it, the runtime terminates your application.
Invalid values do not continue to propagate through the system as a result of code that fails to check for a failure
return code.

Common Exceptions
The following table lists some common exceptions with examples of what can cause them.

EXCEPTION TYPE BASE TYPE DESCRIPTION EXAMPLE

Exception Object Base class for all exceptions. None (use a derived class of
this exception).

IndexOutOfRangeException Exception Thrown by the runtime only Indexing an array outside its
when an array is indexed valid range:
improperly. arr[arr.Length+1]
EXCEPTION TYPE BASE TYPE DESCRIPTION EXAMPLE

NullReferenceException Exception Thrown by the runtime only object o = null;


when a null object is o.ToString();
referenced.

InvalidOperationException Exception Thrown by methods when in Calling


an invalid state. Enumerator.GetNext()
after removing an Item from
the underlying collection.

ArgumentException Exception Base class for all argument None (use a derived class of
exceptions. this exception).

ArgumentNullException Exception Thrown by methods that do String s = null;


not allow an argument to be "Calculate".IndexOf
(s);
null.

ArgumentOutOfRangeExcep Exception Thrown by methods that String s = "string";


tion verify that arguments are in s.Substring(s.Length+1);
a given range.

See Also
Exception Class and Properties
How to: Use the Try-Catch Block to Catch Exceptions
How to: Use Specific Exceptions in a Catch Block
How to: Explicitly Throw Exceptions
How to: Create User-Defined Exceptions
Using User-Filtered Exception Handlers
How to: Use Finally Blocks
Handling COM Interop Exceptions
Best Practices for Exceptions
To learn more about how exceptions work in .NET, see What Every Dev needs to Know About Exceptions in the
Runtime.
.NET Assembly File Format
8/10/2017 • 2 min to read • Edit Online

.NET defines a binary file format - "assembly" - that is used to fully-describe and contain .NET programs.
Assemblies are used for the programs themselves as well as any dependent libraries. A .NET program can be
executed as one of more assemblies, with no other required artifacts, beyond the appropriate .NET implementation.
Native dependencies, including operating system APIs, are a separate concern and are not contained within the
.NET assembly format, although are sometimes described with this format (for example, WinRT).

Each CLI component carries the metadata for declarations, implementations, and references specific to that
component. Therefore, the component-specific metadata is referred to as component metadata, and the
resulting component is said to be self-describing – from ECMA 335 I.9.1, Components and assemblies.

The format is fully specified and standardized as ECMA 335. All .NET compilers and runtimes use this format. The
presence of a documented and infrequently updated binary format has been a major benefit (arguably a
requirement) for interoperatibility. The format was last updated in a substantive way in 2005 (.NET 2.0) to
accommodate generics and processor architecture.
The format is CPU- and OS-agnostic. It has been used as part of .NET implementations that target many chips and
CPUs. While the format itself has Windows heritage, it is implementable on any operating system. It’s arguably
most significant choice for OS interoperability is that most values are stored in little-endian format. It doesn’t have
a specific affinity to machine pointer size (for example, 32-bit, 64-bit).
The .NET assembly format is also very descriptive about the structure of a given program or library. It describes the
internal components of an assembly, specifically: assembly references and types defined and their internal
structure. Tools or APIs can read and process this information for display or to make programmatic decisions.

Format
The .NET binary format is based on the Windows PE file format. In fact, .NET class libraries are conformant
Windows PEs, and appear on first glance to be Windows dynamic link libraries (DLLs) or application executables
(EXEs). This is a very useful characteristic on Windows, where they can masquerade as native executable binaries
and get some of the same treatment (for example, OS load, PE tools).
Assembly Headers from ECMA 335 II.25.1, Structure of the runtime file format.

Processing the Assemblies


It is possible to write tools or APIs to process assemblies. Assembly information enables making programmatic
decisions at runtime, re-writing assemblies, providing API IntelliSense in an editor and generating documentation.
System.Reflection and Mono.Cecil are good examples of tools that are frequently used for this purpose.
Memory Management and Garbage Collection in
.NET
7/29/2017 • 1 min to read • Edit Online

This section of the documentation provides information about managing memory in .NET.

In This Section
Cleaning Up Unmanaged Resources
Describes how to properly manage and clean up unmanaged resources..
Garbage Collection
Provides information about the .NET garbage collector.

Related Sections
Development Guide
Generic Types (Generics) Overview
8/10/2017 • 3 min to read • Edit Online

We use generics all the time in C#, whether implicitly or explicitly. When you use LINQ in C#, did you ever notice
that you are working with IEnumerable? Or if you ever saw an online sample of a "generic repository" for talking to
databases using Entity Framework, did you see that most methods return IQueryable? You may have wondered
what the T is in these examples and why is it in there?
First introduced to the .NET Framework 2.0, generics involved changes to both the C# language and the Common
Language Runtime (CLR). Generics are essentially a "code template" that allows developers to define type-safe
data structures without committing to an actual data type. For example, List<T> is a Generic Collection that can be
declared and used with any type: List<int> , List<string> , List<Person> , etc.
So, what’s the point? Why are generics useful? In order to understand this, we need to take a look at a specific class
before and after adding generics. Let’s look at the ArrayList . In C# 1.0, the ArrayList elements were of type
object . This meant that any element that was added was silently converted into an object ; same thing happens
on reading the elements from the list (this process is known as boxing and unboxing respectively). Boxing and
unboxing have an impact of performance. More than that, however, there is no way to tell at compile time what is
the actual type of the data in the list. This makes for some fragile code. Generics solve this problem by providing
additional information the type of data each instance of list will contain. Put simply, you can only add integers to
List<int> and only add Persons to List<Person> , etc.

Generics are also available at runtime, or reified. This means the runtime knows what type of data structure you
are using and can store it in memory more efficiently.
Here is a small program that illustrates the efficiency of knowing the data structure type at runtime:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace GenericsExample {
class Program {
static void Main(string[] args) {
//generic list
List<int> ListGeneric = new List<int> { 5, 9, 1, 4 };
//non-generic list
ArrayList ListNonGeneric = new ArrayList { 5, 9, 1, 4 };
// timer for generic list sort
Stopwatch s = Stopwatch.StartNew();
ListGeneric.Sort();
s.Stop();
Console.WriteLine($"Generic Sort: {ListGeneric} \n Time taken: {s.Elapsed.TotalMilliseconds}ms");

//timer for non-generic list sort


Stopwatch s2 = Stopwatch.StartNew();
ListNonGeneric.Sort();
s2.Stop();
Console.WriteLine($"Non-Generic Sort: {ListNonGeneric} \n Time taken:
{s2.Elapsed.TotalMilliseconds}ms");
Console.ReadLine();
}
}
}
This program yields the following output:

Generic Sort: System.Collections.Generic.List\`1[System.Int32] Time taken: 0.0789ms


Non-Generic Sort: System.Collections.ArrayList Time taken: 2.4324ms

The first thing you notice here is that sorting the generic list is significantly faster than for the non-generic list. You
might also notice that the type for the generic list is distinct ([System.Int32]) whereas the type for the non-generic
list is generalized. Because the runtime knows the generic List<int> is of type int, it can store the list elements in
an underlying integer array in memory while the non-generic ArrayList has to cast each list element as an object
as stored in an object array in memory. As shown through this example, the extra castings take up time and slow
down the list sort.
The last useful thing about the runtime knowing the type of your generic is a better debugging experience. When
you are debugging a generic in C#, you know what type each element is in your data structure. Without generics,
you would have no idea what type each element was.

Further reading and resources


An Introduction to C# Generics
C# Programming Guide - Generics
Delegates and lambdas
7/29/2017 • 4 min to read • Edit Online

Delegates define a type, which specify a particular method signature. A method (static or instance) that satisfies this
signature can be assigned to a variable of that type, then called directly (with the appropriate arguments) or passed
as an argument itself to another method and then called. The following example demonstrates delegate use.

public class Program


{

public delegate string Reverse(string s);

static string ReverseString(string s)


{
return new string(s.Reverse().ToArray());
}

static void Main(string[] args)


{
Reverse rev = ReverseString;

Console.WriteLine(rev("a string"));
}
}

On line 4 we create a delegate type of a certain signature, in this case a method that takes a string parameter
and then returns a string parameter.
On line 6, we define the implementation of the delegate by providing a method that has the exact same
signature.
On line 13, the method is assigned to a type that conforms to the Reverse delegate.
Finally, on line 15 we invoke the delegate passing a string to be reversed.
In order to streamline the development process, .NET includes a set of delegate types that programmers can reuse
and not have to create new types. These are Func<> , Action<> and Predicate<> , and they can be used in various
places throughout the .NET APIs without the need to define new delegate types. Of course, there are some
differences between the three as you will see in their signatures which mostly have to do with the way they were
meant to be used:
Action<> is used when there is a need to perform an action using the arguments of the delegate.
Func<> is used usually when you have a transformation on hand, that is, you need to transform the arguments
of the delegate into a different result. Projections are a prime example of this.
Predicate<> is used when you need to determine if the argument satisfies the condition of the delegate. It can
also be written as a Func<T, bool> .
We can now take our example above and rewrite it using the Func<> delegate instead of a custom type. The
program will continue running exactly the same.
public class Program
{

static string ReverseString(string s)


{
return new string(s.Reverse().ToArray());
}

static void Main(string[] args)


{
Func<string, string> rev = ReverseString;

Console.WriteLine(rev("a string"));
}
}

For this simple example, having a method defined outside of the Main() method seems a bit superfluous. It is
because of this that .NET Framework 2.0 introduced the concept of anonymous delegates. With their support you
are able to create "inline" delegates without having to specify any additional type or method. You simply inline the
definition of the delegate where you need it.
For an example, we are going to switch it up and use our anonymous delegate to filter out a list of only even
numbers and then print them to the console.

public class Program


{

public static void Main(string[] args)


{
List<int> list = new List<int>();

for (int i = 1; i <= 100; i++)


{
list.Add(i);
}

List<int> result = list.FindAll(


delegate(int no)
{
return (no%2 == 0);
}
);

foreach (var item in result)


{
Console.WriteLine(item);
}
}
}

Notice the highlighted lines. As you can see, the body of the delegate is just a set of expressions, as any other
delegate. But instead of it being a separate definition, we’ve introduced it ad hoc in our call to the FindAll()
method of the List<T> type.
However, even with this approach, there is still much code that we can throw away. This is where lambda
expressions come into play.
Lambda expressions, or just "lambdas" for short, were introduced first in C# 3.0, as one of the core building blocks
of Language Integrated Query (LINQ). They are just a more convenient syntax for using delegates. They declare a
signature and a method body, but don’t have an formal identity of their own, unless they are assigned to a
delegate. Unlike delegates, they can be directly assigned as the left-hand side of event registration or in various
Linq clauses and methods.
Since a lambda expression is just another way of specifying a delegate, we should be able to rewrite the above
sample to use a lambda expression instead of an anonymous delegate.

public class Program


{

public static void Main(string[] args)


{
List<int> list = new List<int>();

for (int i = 1; i <= 100; i++)


{
list.Add(i);
}

List<int> result = list.FindAll(i => i % 2 == 0);

foreach (var item in result)


{
Console.WriteLine(item);
}
}
}

If you take a look at the highlighted lines, you can see how a lambda expression looks like. Again, it is just a very
convenient syntax for using delegates, so what happens under the covers is similar to what happens with the
anonymous delegate.
Again, lambdas are just delegates, which means that they can be used as an event handler without any problems,
as the following code snippet illustrates.

public MainWindow()
{
InitializeComponent();

Loaded += (o, e) =>


{
this.Title = "Loaded";
};
}

Further reading and resources


Delegates
Anonymous Functions
Lambda expressions
LINQ (Language Integrated Query)
7/29/2017 • 5 min to read • Edit Online

What is it?
LINQ provides language-level querying capabilities and a higher-order function API to C# and VB as a way to write
expressive, declarative code.
Language-level query syntax:

var linqExperts = from p in programmers


where p.IsNewToLINQ
select new LINQExpert(p);

Same example using the IEnumerable<T> API:

var linqExperts = programmers.Where(p => IsNewToLINQ)


.Select(p => new LINQExpert(p));

LINQ is Expressive
Imagine you have a list of pets, but want to convert it into a dictionary where you can access a pet directly by its
RFID value.

Traditional imperative code:

var petLookup = new Dictionary<int, Pet>();

foreach (var pet in pets)


{
petLookup.Add(pet.RFID, pet);
}

The intention behind the code is not to create a new Dictionary<int, Pet> and add to it via a loop, it is to convert
an existing list into a dictionary! LINQ preserves the intention whereas the imperative code does not.
Equivalent LINQ expression:

var petLookup = pets.ToDictionary(pet => pet.RFID);

The code using LINQ is valuable because it evens the playing field between intent and code when reasoning as a
programmer. Another bonus is code brevity. Imagine reducing large portions of a codebase by 1/3 as done above.
Pretty sweet deal, right?

LINQ Providers Simplify Data Access


For a significant chunk of software out in the wild, everything revolves around dealing with data from some source
(Databases, JSON, XML, etc). Often this involves learning a new API for each data source, which can be annoying.
LINQ simplifies this by abstracting common elements of data access into a query syntax which looks the same no
matter which data source you pick.
Consider the following: finding all XML elements with a specific attribute value.

public static IEnumerable<XElement> FindAllElementsWithAttribute(XElement documentRoot, string elementName,


string attributeName, string value)
{
return from el in documentRoot.Elements(elementName)
where (string)el.Element(attributeName) == value
select el;
}

Writing code to manually traverse the XML document to perform this task would be far more challenging.
Interacting with XML isn’t the only thing you can do with LINQ Providers. Linq to SQL is a fairly bare-bones Object-
Relational Mapper (ORM) for an MSSQL Server Database. The JSON.NET library provides efficient JSON Document
traversal via LINQ. Furthermore, if there isn’t a library which does what you need, you can also write your own
LINQ Provider!

Why Use the Query Syntax?


This is a question which often comes up. After all, this,

var filteredItems = myItems.Where(item => item.Foo);

is a lot more concise than this:

var filteredItems = from item in myItems


where item.Foo
select item;

Isn’t the API syntax just a more concise way to do the query syntax?
No. The query syntax allows for the use the let clause, which allows you to introduce and bind a variable within the
scope of the expression, using it in subsequent pieces of the expression. Reproducing the same code with only the
API syntax can be done, but will most likely lead to code which is hard to read.
So this begs the question, should you just use the query syntax?
The answer to this question is yes if...
Your existing codebase already uses the query syntax
You need to scope variables within your queries due to complexity
You prefer the query syntax and it won’t distract from your codebase
The answer to this question is no if...
Your existing codebase already uses the API syntax
You have no need to scope variables within your queries
You prefer the API syntax and it won’t distract from your codebase

Essential Samples
For a truly comprehensive list of LINQ samples, visit 101 LINQ Samples.
The following is a quick demonstration of some of the essential pieces of LINQ. This is in no way comprehensive, as
LINQ provides significantly more functionality than what is showcased here.
The bread and butter - Where , Select , and Aggregate :

// Filtering a list
var germanShepards = dogs.Where(dog => dog.Breed == DogBreed.GermanShepard);

// Using the query syntax


var queryGermanShepards = from dog in dogs
where dog.Breed == DogBreed.GermanShepard
select dog;

// Mapping a list from type A to type B


var cats = dogs.Select(dog => dog.TurnIntoACat());

// Using the query syntax


var queryCats = from dog in dogs
select dog.TurnIntoACat();

// Summing then lengths of a set of strings


int seed = 0;
int sumOfStrings = strings.Aggregate(seed, (s1, s2) => s1.Length + s2.Length);

Flattening a list of lists:

// Transforms the list of kennels into a list of all their dogs.


var allDogsFromKennels = kennels.SelectMany(kennel => kennel.Dogs);

Union between two sets (with custom comparator):

public class DogHairLengthComparer : IEqualityComparer<Dog>


{
public bool Equals(Dog a, Dog b)
{
if (a == null && b == null)
{
return true;
}
else if ((a == null && b != null) ||
(a != null && b == null))
{
return false;
}
else
{
return a.HairLengthType == b.HairLengthType;
}
}

public int GetHashCode(Dog d)


{
// default hashcode is enough here, as these are simple objects.
return b.GetHashCode();
}
}

...

// Gets all the short-haired dogs between two different kennels


var allShortHairedDogs = kennel1.Dogs.Union(kennel2.Dogs, new DogHairLengthComparer());

Intersection between two sets:


// Gets the volunteers who spend share time with two humane societies.
var volunteers = humaneSociety1.Volunteers.Intersect(humaneSociety2.Volunteers,
new VolunteerTimeComparer());

Ordering:

// Get driving directions, ordering by if it's toll-free before estimated driving time.
var results = DirectionsProcessor.GetDirections(start, end)
.OrderBy(direction => direction.HasNoTolls)
.ThenBy(direction => direction.EstimatedTime);

Finally, a more advanced sample: determining if the values of the properties of two instances of the same type
are equal (Borrowed and modified from this StackOverflow post):

public static bool PublicInstancePropertiesEqual<T>(this T self, T to, params string[] ignore) where T : class
{
if (self != null && to != null)
{
var type = typeof(T);
var ignoreList = new List<string>(ignore);

// Selects the properties which have unequal values into a sequence of those properties.
var unequalProperties = from pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
where !ignoreList.Contains(pi.Name)
let selfValue = type.GetProperty(pi.Name).GetValue(self, null)
let toValue = type.GetProperty(pi.Name).GetValue(to, null)
where selfValue != toValue && (selfValue == null ||
!selfValue.Equals(toValue))
select new { Prop = pi.Name, selfValue, toValue };
return !unequalProperties.Any();
}

return self == to;


}

PLINQ
PLINQ, or Parallel LINQ, is a parallel execution engine for LINQ expressions. In other words, a regular LINQ
expressions can be trivially parallelized across any number of threads. This is accomplished via a call to
AsParallel() preceding the expression.

Consider the following:

public static string GetAllFacebookUserLikesMessage(IEnumerable<FacebookUser> facebookUsers)


{
var seed = default(UInt64);

Func<UInt64, UInt64, UInt64> threadAccumulator = (t1, t2) => t1 + t2;


Func<UInt64, UInt64, UInt64> threadResultAccumulator = (t1, t2) => t1 + t2;
Func<Uint64, string> resultSelector = total => $"Facebook has {total} likes!";

return facebookUsers.AsParallel()
.Aggregate(seed, threadAccumulator, threadResultAccumulator, resultSelector);
}

This code will partition facebookUsers across system threads as necessary, sum up the total likes on each thread in
parallel, sum the results computed by each thread, and project that result into a nice string.
In diagram form:

Parallelizable CPU-bound jobs which can be easily expressed via LINQ (in other words, are pure functions and have
no side effects) are a great candidate for PLINQ. For jobs which do have a side effect, consider using the Task
Parallel Library.

Further Resources:
101 LINQ Samples
Linqpad, a playground environment and Database querying engine for C#/F#/VB
EduLinq, an e-book for learning how LINQ-to-objects is implemented
Common Type System & Common Language
Specification
8/5/2017 • 2 min to read • Edit Online

Again, two terms that are freely used in the .NET world, they actually are crucial to understand how a .NET
implementation enables multi-language development and to understand how it works.

Common Type System


To start from the beginning, remember that a .NET implementation is language agnostic. This doesn’t just mean
that a programmer can write her code in any language that can be compiled to IL. It also means that she needs to
be able to interact with code written in other languages that are able to be used on a .NET implementation.
In order to do this transparently, there has to be a common way to describe all supported types. This is what the
Common Type System (CTS) is in charge of doing. It was made to do several things:
Establish a framework for cross-language execution.
Provide an object-oriented model to support implementing various languages on a .NET implementation.
Define a set of rules that all languages must follow when it comes to working with types.
Provide a library that contains the basic primitive types that are used in application development (such as,
Boolean , Byte , Char etc.)

CTS defines two main kinds of types that should be supported: reference and value types. Their names point to
their definitions.
Reference types’ objects are represented by a reference to the object’s actual value; a reference here is similar to a
pointer in C/C++. It simply refers to a memory location where the objects’ values are. This has a profound impact
on how these types are used. If you assign a reference type to a variable and then pass that variable into a method,
for instance, any changes to the object will be reflected on the main object; there is no copying.
Value types are the opposite, where the objects are represented by their values. If you assign a value type to a
variable, you are essentially copying a value of the object.
CTS defines several categories of types, each with their specific semantics and usage:
Classes
Structures
Enums
Interfaces
Delegates
CTS also defines all other properties of the types, such as access modifiers, what are valid type members, how
inheritance and overloading works and so on. Unfortunately, going deep into any of those is beyond the scope of
an introductory article such as this, but you can consult More resources section at the end for links to more in-
depth content that covers these topics.

Common Language Specification


To enable full interoperability scenarios, all objects that are created in code must rely on some commonality in the
languages that are consuming them (are their callers). Since there are numerous different languages, .NET has
specified those commonalities in something called the Common Language Specification (CLS). CLS defines a
set of features that are needed by many common applications. It also provides a sort of recipe for any language
that is implemented on top of .NET on what it needs to support.
CLS is a subset of the CTS. This means that all of the rules in the CTS also apply to the CLS, unless the CLS rules are
more strict. If a component is built using only the rules in the CLS, that is, it exposes only the CLS features in its API,
it is said to be CLS-compliant. For instance, the <framework-librares> are CLS-compliant precisely because they
need to work across all of the languages that are supported on .NET.
You can consult the documents in the More Resources section below to get an overview of all the features in the
CLS.

More resources
Common Type System
Common Language Specification
Async Overview
7/29/2017 • 1 min to read • Edit Online

Not so long ago, apps got faster simply by buying a newer PC or server and then that trend stopped. In fact, it
reversed. Mobile phones appeared with 1ghz single core ARM chips and server workloads transitioned to VMs.
Users still want responsive UI and business owners want servers that scale with their business. The transition to
mobile and cloud and an internet-connected population of >3B users has resulted in a new set of software
patterns.
Client applications are expected to be always-on, always-connected and constantly responsive to user
interaction (for example, touch) with high app store ratings!
Services are expected to handle spikes in traffic by gracefully scaling up and down.
Async programming is a key technique that makes it straightforward to handle blocking I/O and concurrent
operations on multiple cores. .NET provides the capability for apps and services to be responsive and elastic with
easy-to-use, language-level asynchronous programming models in C#, VB, and F#.

Why Write Async Code?


Modern apps make extensive use of file and networking I/O. I/O APIs traditionally block by default, resulting in
poor user experiences and hardware utilization unless you want to learn and use challenging patterns. Task-based
async APIs and the language-level asynchronous programming model invert this model, making async execution
the default with few new concepts to learn.
Async code has the following characteristics:
Handles more server requests by yielding threads to handle more requests while waiting for I/O requests to
return.
Enables UIs to be more responsive by yielding threads to UI interaction while waiting for I/O requests and by
transitioning long-running work to other CPU cores.
Many of the newer .NET APIs are asynchronous.
It's easy to write async code in .NET!

What's next?
For a deep dive into async concepts and programming, see Async in depth and Task-based asynchronous
programming.
Async in depth
8/29/2017 • 9 min to read • Edit Online

Writing I/O- and CPU-bound asynchronous code is straightforward using the .NET Task-based async model. The
model is exposed by the Task and Task<T> types and the async and await keywords in C# and Visual Basic.
(Language-specific resources are found in the See also section.) This article explains how to use .NET async and
provides insight into the async framework used under the covers.

Task and Task<T>


Tasks are constructs used to implement what is known as the Promise Model of Concurrency. In short, they offer
you a "promise" that work will be completed at a later point, letting you coordinate with the promise with a clean
API.
Task represents a single operation which does not return a value.
Task<T> represents a single operation which returns a value of type T .
It’s important to reason about tasks as abstractions of work happening asynchronously, and not an abstraction
over threading. By default, tasks execute on the current thread and delegate work to the Operating System, as
appropriate. Optionally, tasks can be explicitly requested to run on a separate thread via the Task.Run API.
Tasks expose an API protocol for monitoring, waiting upon and accessing the result value (in the case of Task<T> )
of a task. Language integration, with the await keyword, provides a higher-level abstraction for using tasks.
Using await allows your application or service to perform useful work while a task is running by yielding control
to its caller until the task is done. Your code does not need to rely on callbacks or events to continue execution
after the task has been completed. The language and task API integration does that for you. If you’re using
Task<T> , the await keyword will additionally "unwrap" the value returned when the Task is complete. The details
of how this works are explained further below.
You can learn more about tasks and the different ways to interact with them in the Task-based Asynchronous
Pattern (TAP) topic.

Deeper Dive into Tasks for an I/O-Bound Operation


The following section describes a 10,000 foot view of what happens with a typical async I/O call. Let's start with a
couple examples.
The first example calls an async method and returns an active task, likely yet to complete.

public Task<string> GetHtmlAsync()


{
// Execution is synchronous here
var client = new HttpClient();

return client.GetStringAsync("http://www.dotnetfoundation.org");
}

The second example adds the use of the async and await keywords to operate on the task.
public async Task<string> GetFirstCharactersCountAsync(string url, int count)
{
// Execution is synchronous here
var client = new HttpClient();

// Execution of GetFirstCharactersCountAsync() is yielded to the caller here


// GetStringAsync returns a Task<string>, which is *awaited*
var page = await client.GetStringAsync("http://www.dotnetfoundation.org");

// Execution resumes when the client.GetStringAsync task completes,


// becoming synchronous again.

if (count > page.Length)


{
return page;
}
else
{
return page.Substring(0, count);
}
}

The call to GetStringAsync() calls through lower-level .NET libraries (perhaps calling other async methods) until it
reaches a P/Invoke interop call into a native networking library. The native library may subsequently call into a
System API call (such as write() to a socket on Linux). A task object will be created at the native/managed
boundary, possibly using TaskCompletionSource. The task object will be passed up through the layers, possibly
operated on or directly returned, eventually returned to the initial caller.
In the second example above, a Task<T> object will be returned from GetStringAsync . The use of the await
keyword causes the method to return a newly created task object. Control returns to the caller from this location in
the GetFirstCharactersCountAsync method. The methods and properties of the Task<T> object enable callers to
monitor the progress of the task, which will complete when the remaining code in GetFirstCharactersCountAsync
has executed.
After the System API call, the request is now in kernel space, making its way to the networking subsystem of the
OS (such as /net in the Linux Kernel). Here the OS will handle the networking request asynchronously. Details
may be different depending on the OS used (the device driver call may be scheduled as a signal sent back to the
runtime, or a device driver call may be made and then a signal sent back), but eventually the runtime will be
informed that the networking request is in progress. At this time, the work for the device driver will either be
scheduled, in-progress, or already finished (the request is already out "over the wire") - but because this is all
happening asynchronously, the device driver is able to immediately handle something else!
For example, in Windows an OS thread makes a call to the network device driver and asks it to perform the
networking operation via an Interrupt Request Packet (IRP) which represents the operation. The device driver
receives the IRP, makes the call to the network, marks the IRP as "pending", and returns back to the OS. Because
the OS thread now knows that the IRP is "pending", it doesn't have any more work to do for this job and "returns"
back so that it can be used to perform other work.
When the request is fulfilled and data comes back through the device driver, it notifies the CPU of new data
received via an interrupt. How this interrupt gets handled will vary depending on the OS, but eventually the data
will be passed through the OS until it reaches a system interop call (for example, in Linux an interrupt handler will
schedule the bottom half of the IRQ to pass the data up through the OS asynchronously). Note that this also
happens asynchronously! The result is queued up until the next available thread is able execute the async method
and "unwrap" the result of the completed task.
Throughout this entire process, a key takeaway is that no thread is dedicated to running the task. Although
work is executed in some context (that is, the OS does have to pass data to a device driver and respond to an
interrupt), there is no thread dedicated to waiting for data from the request to come back. This allows the system
to handle a much larger volume of work rather than waiting for some I/O call to finish.
Although the above may seem like a lot of work to be done, when measured in terms of wall clock time, it’s
miniscule compared to the time it takes to do the actual I/O work. Although not at all precise, a potential timeline
for such a call would look like this:
0-1
————————————————————————————————————————————————–2-
3
Time spent from points 0 to 1 is everything up until an async method yields control to its caller.
Time spent from points 1 to 2 is the time spent on I/O, with no CPU cost.
Finally, time spent from points 2 to 3 is passing control back (and potentially a value) to the async method, at
which point it is executing again.
What does this mean for a server scenario?
This model works well with a typical server scenario workload. Because there are no threads dedicated to blocking
on unfinished tasks, the server threadpool can service a much higher volume of web requests.
Consider two servers: one that runs async code, and one that does not. For the purpose of this example, each
server only has 5 threads available to service requests. Note that these numbers are imaginarily small and serve
only in a demonstrative context.
Assume both servers receive 6 concurrent requests. Each request performs an I/O operation. The server without
async code has to queue up the 6th request until one of the 5 threads have finished the I/O-bound work and
written a response. At the point that the 20th request comes in, the server might start to slow down, because the
queue is getting too long.
The server with async code running on it still queues up the 6th request, but because it uses async and await ,
each of its threads are freed up when the I/O-bound work starts, rather than when it finishes. By the time the 20th
request comes in, the queue for incoming requests will be far smaller (if it has anything in it at all), and the server
won't slow down.
Although this is a contrived example, it works in a very similar fashion in the real world. In fact, you can expect a
server to be able to handle an order of magnitude more requests using async and await than if it were
dedicating a thread for each request it receives.
What does this mean for client scenario?
The biggest gain for using async and await for a client app is an increase in responsiveness. Although you can
make an app responsive by spawning threads manually, the act of spawning a thread is an expensive operation
relative to just using async and await . Especially for something like a mobile game, impacting the UI thread as
little as possible where I/O is concerned is crucial.
More importantly, because I/O-bound work spends virtually no time on the CPU, dedicating an entire CPU thread
to perform barely any useful work would be a poor use of resources.
Additionally, dispatching work to the UI thread (such as updating a UI) is very simple with async methods, and
does not require extra work (such as calling a thread-safe delegate).

Deeper Dive into Task and Task for a CPU-Bound Operation


CPU-bound async code is a bit different than I/O-bound async code. Because the work is done on the CPU,
there's no way to get around dedicating a thread to the computation. The use of async and await provides you
with a clean way to interact with a background thread and keep the caller of the async method responsive. Note
that this does not provide any protection for shared data. If you are using shared data, you will still need to apply
an appropriate synchronization strategy.
Here's a 10,000 foot view of a CPU-bound async call:

public async Task<int> CalculateResult(InputData data)


{
// This queues up the work on the threadpool.
var expensiveResultTask = Task.Run(() => DoExpensiveCalculation(data));

// Note that at this point, you can do some other work concurrently,
// as CalculateResult() is still executing!

// Execution of CalculateResult is yielded here!


var result = await expensiveResultTask;

return result;
}

CalculateResult() executes on the thread it was called on. When it calls Task.Run , it queues the expensive CPU-
bound operation, DoExpensiveCalculation() , on the thread pool and receives a Task<int> handle.
DoExpensiveCalculation() is eventually run concurrently on the next available thread, likely on another CPU core.
It's possible to do concurrent work while DoExpensiveCalculation() is busy on another thread, because the thread
which called CalculateResult() is still executing.
Once await is encountered, the execution of CalculateResult() is yielded to its caller, allowing other work to be
done with the current thread while DoExpensiveCalculation() is churning out a result. Once it has finished, the
result is queued up to run on the main thread. Eventually, the main thread will return to executing
CalculateResult() , at which point it will have the result of DoExpensiveCalculation() .

Why does async help here?


async and await are the best practice managing CPU-bound work when you need responsiveness. There are
multiple patterns for using async with CPU-bound work. It's important to note that there is a small cost to using
async and it's not recommended for tight loops. It's up to you to determine how you write your code around this
new capability.

See also
Asynchronous programming in C#
Async Programming in F#
Asynchronous Programming with Async and Await (Visual Basic)
Asynchronous Programming Patterns
7/29/2017 • 2 min to read • Edit Online

The .NET Framework provides three patterns for performing asynchronous operations:
Asynchronous Programming Model (APM) pattern (also called the IAsyncResult pattern), where
asynchronous operations require Begin and End methods (for example, BeginWrite and EndWrite for
asynchronous write operations). This pattern is no longer recommended for new development. For more
information, see Asynchronous Programming Model (APM).
Event-based Asynchronous Pattern (EAP), which requires a method that has the Async suffix, and also
requires one or more events, event handler delegate types, and EventArg -derived types. EAP was
introduced in the .NET Framework 2.0. It is no longer recommended for new development. For more
information, see Event-based Asynchronous Pattern (EAP).
Task-based Asynchronous Pattern (TAP), which uses a single method to represent the initiation and
completion of an asynchronous operation. TAP was introduced in the .NET Framework 4 and is the
recommended approach to asynchronous programming in the .NET Framework. The async and await
keywords in C# and the Async and Await operators in Visual Basic Language add language support for TAP.
For more information, see Task-based Asynchronous Pattern (TAP).

Comparing Patterns
For a quick comparison of how the three patterns model asynchronous operations, consider a Read method that
reads a specified amount of data into a provided buffer starting at a specified offset:

public class MyClass


{
public int Read(byte [] buffer, int offset, int count);
}

The APM counterpart of this method would expose the BeginRead and EndRead methods:

public class MyClass


{
public IAsyncResult BeginRead(
byte [] buffer, int offset, int count,
AsyncCallback callback, object state);
public int EndRead(IAsyncResult asyncResult);
}

The EAP counterpart would expose the following set of types and members:

public class MyClass


{
public void ReadAsync(byte [] buffer, int offset, int count);
public event ReadCompletedEventHandler ReadCompleted;
}

The TAP counterpart would expose the following single ReadAsync method:
public class MyClass
{
public Task<int> ReadAsync(byte [] buffer, int offset, int count);
}

For a comprehensive discussion of TAP, APM, and EAP, see the links provided in the next section.

Related topics
TITLE DESCRIPTION

Asynchronous Programming Model (APM) Describes the legacy model that uses the IAsyncResult
interface to provide asynchronous behavior. This model is no
longer recommended for new development.

Event-based Asynchronous Pattern (EAP) Describes the event-based legacy model for providing
asynchronous behavior. This model is no longer recommended
for new development.

Task-based Asynchronous Pattern (TAP) Describes the new asynchronous pattern based on the
System.Threading.Tasks namespace. This model is the
recommended approach to asynchronous programming in the
.NET Framework 4 and later versions.

See also
Asynchronous programming in C#
Async Programming in F#
Asynchronous Programming with Async and Await (Visual Basic)
Native Interoperability
8/5/2017 • 10 min to read • Edit Online

In this document, we will dive a little bit deeper into all three ways of doing "native interoperability" that are
available using .NET.
There are a few of reasons why you would want to call into native code:
Operating Systems come with a large volume of APIs that are not present in the managed class libraries. A
prime example for this would be access to hardware or operating system management functions.
Communicating with other components that have or can produce C-style ABIs (native ABIs). This covers, for
example, Java code that is exposed via Java Native Interface (JNI) or any other managed language that could
produce a native component.
On Windows, most of the software that gets installed, such as Microsoft Office suite, registers COM
components that represent their programs and allow developers to automate them or use them. This also
requires native interoperability.
Of course, the list above does not cover all of the potential situations and scenarios in which the developer would
want/like/need to interface with native components. .NET class library, for instance, uses the native interoperability
support to implement a fair number of its APIs, like console support and manipulation, file system access and
others. However, it is important to note that there is an option, should one need it.

NOTE
Most of the examples in this document will be presented for all three supported platforms for .NET Core (Windows, Linux
and macOS). However, for some short and illustrative examples, just one sample is shown that uses Windows filenames and
extensions (that is, "dll" for libraries). This does not mean that those features are not available on Linux or macOS, it was
done merely for convenience sake.

Platform Invoke (P/Invoke)


P/Invoke is a technology that allows you to access structs, callbacks and functions in unmanaged libraries from
your managed code. Most of the P/Invoke API is contained in two namespaces: System and
System.Runtime.InteropServices . Using these two namespaces will allow you access to the attributes that describe
how you want to communicate with the native component.
Let’s start from the most common example, and that is calling unmanaged functions in your managed code. Let’s
show a message box from a command-line application:
using System.Runtime.InteropServices;

public class Program {

// Import user32.dll (containing the function we need) and define


// the method corresponding to the native function.
[DllImport("user32.dll")]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, int options);

public static void Main(string[] args) {


// Invoke the function as a regular managed method.
MessageBox(IntPtr.Zero, "Command-line message box", "Attention!", 0);
}
}

The example above is pretty simple, but it does show off what is needed to invoke unmanaged functions from
managed code. Let’s step through the example:
Line #1 shows the using statement for the System.Runtime.InteropServices which is the namespace that holds
all of the items we need.
Line #5 introduces the DllImport attribute. This attribute is crucial, as it tells the runtime that it should load the
unmanaged DLL. This is the DLL into which we wish to invoke.
Line #6 is the crux of the P/Invoke work. It defines a managed method that has the exact same signature as
the unmanaged one. The declaration has a new keyword that you can notice, extern , which tells the runtime
this is an external method, and that when you invoke it, the runtime should find it in the DLL specified in
DllImport attribute.

The rest of the example is just invoking the method as you would any other managed method.
The sample is similar for macOS. One thing that needs to change is, of course, the name of the library in the
DllImport attribute, as macOS has a different scheme of naming dynamic libraries. The sample below uses the
getpid(2) function to get the process ID of the application and print it out to the console.

using System;
using System.Runtime.InteropServices;

namespace PInvokeSamples {
public static class Program {

// Import the libc and define the method corresponding to the native function.
[DllImport("libSystem.dylib")]
private static extern int getpid();

public static void Main(string[] args){


// Invoke the function and get the process ID.
int pid = getpid();
Console.WriteLine(pid);
}
}
}

It is similar on Linux, of course. The function name is same, since getpid(2) is POSIX system call.
using System;
using System.Runtime.InteropServices;

namespace PInvokeSamples {
public static class Program {

// Import the libc and define the method corresponding to the native function.
[DllImport("libc.so.6")]
private static extern int getpid();

public static void Main(string[] args){


// Invoke the function and get the process ID.
int pid = getpid();
Console.WriteLine(pid);
}
}
}

Invoking managed code from unmanaged code


Of course, the runtime allows communication to flow both ways which enables you to call into managed artifacts
from native functions, using function pointers. The closest thing to a function pointer in managed code is a
delegate, so this is what is used to allow callbacks from native code into managed code.
The way to use this feature is similar to managed to native process described above. For a given callback, you
define a delegate that matches the signature, and pass that into the external method. The runtime will take care of
everything else.

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication1 {

class Program {

// Define a delegate that corresponds to the unmanaged function.


delegate bool EnumWC(IntPtr hwnd, IntPtr lParam);

// Import user32.dll (containing the function we need) and define


// the method corresponding to the native function.
[DllImport("user32.dll")]
static extern int EnumWindows(EnumWC lpEnumFunc, IntPtr lParam);

// Define the implementation of the delegate; here, we simply output the window handle.
static bool OutputWindow(IntPtr hwnd, IntPtr lParam) {
Console.WriteLine(hwnd.ToInt64());
return true;
}

static void Main(string[] args) {


// Invoke the method; note the delegate as a first parameter.
EnumWindows(OutputWindow, IntPtr.Zero);
}
}
}

Before we walk through our example, it is good to go over the signatures of the unmanaged functions we need to
work with. The function we want to call to enumerate all of the windows has the following signature:
BOOL EnumWindows (WNDENUMPROC lpEnumFunc, LPARAM lParam);

The first parameter is a callback. The said callback has the following signature:
BOOL CALLBACK EnumWindowsProc (HWND hwnd, LPARAM lParam);
With this in mind, let’s walk through the example:
Line #8 in the example defines a delegate that matches the signature of the callback from unmanaged code.
Notice how the LPARAM and HWND types are represented using IntPtr in the managed code.
Lines #10 and #11 introduce the EnumWindows function from the user32.dll library.
Lines #13 - 16 implement the delegate. For this simple example, we just want to output the handle to the
console.
Finally, in line #19 we invoke the external method and pass in the delegate.
The Linux and macOS examples are shown below. For them, we use the ftw function that can be found in libc ,
the C library. This function is used to traverse directory hierarchies and it takes a pointer to a function as one of its
parameters. The said function has the following signature:
int (*fn) (const char *fpath, const struct stat *sb, int typeflag) .

using System;
using System.Runtime.InteropServices;

namespace PInvokeSamples {
public static class Program {

// Define a delegate that has the same signature as the native function.
delegate int DirClbk(string fName, StatClass stat, int typeFlag);

// Import the libc and define the method to represent the native function.
[DllImport("libc.so.6")]
static extern int ftw(string dirpath, DirClbk cl, int descriptors);

// Implement the above DirClbk delegate;


// this one just prints out the filename that is passed to it.
static int DisplayEntry(string fName, StatClass stat, int typeFlag) {
Console.WriteLine(fName);
return 0;
}

public static void Main(string[] args){


// Call the native function.
// Note the second parameter which represents the delegate (callback).
ftw(".", DisplayEntry, 10);
}
}

// The native callback takes a pointer to a struct. The below class


// represents that struct in managed code. You can find more information
// about this in the section on marshalling below.
[StructLayout(LayoutKind.Sequential)]
public class StatClass {
public uint DeviceID;
public uint InodeNumber;
public uint Mode;
public uint HardLinks;
public uint UserID;
public uint GroupID;
public uint SpecialDeviceID;
public ulong Size;
public ulong BlockSize;
public uint Blocks;
public long TimeLastAccess;
public long TimeLastModification;
public long TimeLastStatusChange;
}
}

macOS example uses the same function, and the only difference is the argument to the DllImport attribute, as
macOS keeps libc in a different place.

using System;
using System.Runtime.InteropServices;

namespace PInvokeSamples {
public static class Program {

// Define a delegate that has the same signature as the native function.
delegate int DirClbk(string fName, StatClass stat, int typeFlag);

// Import the libc and define the method to represent the native function.
[DllImport("libSystem.dylib")]
static extern int ftw(string dirpath, DirClbk cl, int descriptors);

// Implement the above DirClbk delegate;


// this one just prints out the filename that is passed to it.
static int DisplayEntry(string fName, StatClass stat, int typeFlag) {
Console.WriteLine(fName);
return 0;
}

public static void Main(string[] args){


// Call the native function.
// Note the second parameter which represents the delegate (callback).
ftw(".", DisplayEntry, 10);
}
}

// The native callback takes a pointer to a struct. The below class


// represents that struct in managed code. You can find more information
// about this in the section on marshalling below.
[StructLayout(LayoutKind.Sequential)]
public class StatClass {
public uint DeviceID;
public uint InodeNumber;
public uint Mode;
public uint HardLinks;
public uint UserID;
public uint GroupID;
public uint SpecialDeviceID;
public ulong Size;
public ulong BlockSize;
public uint Blocks;
public long TimeLastAccess;
public long TimeLastModification;
public long TimeLastStatusChange;
}
}

Both of the above examples depend on parameters, and in both cases, the parameters are given as managed types.
Runtime does the "right thing" and processes these into its equivalents on the other side. Since this process is
really important to writing quality native interop code, let’s take a look at what happens when the runtime
marshals the types.

Type marshalling
Marshalling is the process of transforming types when they need to cross the managed boundary into native and
vice versa.
The reason marshalling is needed is because the types in the managed and unmanaged code are different. In
managed code, for instance, you have a String , while in the unmanaged world strings can be Unicode ("wide"),
non-Unicode, null-terminated, ASCII, etc. By default, the P/Invoke subsystem will try to do the Right Thing based on
the default behavior which you can see on MSDN. However, for those situations where you need extra control, you
can employ the MarshalAs attribute to specify what is the expected type on the unmanaged side. For instance, if
we want the string to be sent as a null-terminated ANSI string, we could do it like this:

[DllImport("somenativelibrary.dll")]
static extern int MethodA([MarshalAs(UnmanagedType.LPStr)] string parameter);

Marshalling classes and structs


Another aspect of type marshalling is how to pass in a struct to an unmanaged method. For instance, some of the
unmanaged methods require a struct as a parameter. In these cases, we need to create a corresponding struct or a
class in managed part of the world to use it as a parameter. However, just defining the class is not enough, we also
need to instruct the marshaler how to map fields in the class to the unmanaged struct. This is where the
StructLayout attribute comes into play.

[DllImport("kernel32.dll")]
static extern void GetSystemTime(SystemTime systemTime);

[StructLayout(LayoutKind.Sequential)]
class SystemTime {
public ushort Year;
public ushort Month;
public ushort DayOfWeek;
public ushort Day;
public ushort Hour;
public ushort Minute;
public ushort Second;
public ushort Milsecond;
}

public static void Main(string[] args) {


SystemTime st = new SystemTime();
GetSystemTime(st);
Console.WriteLine(st.Year);
}

The example above shows off a simple example of calling into GetSystemTime() function. The interesting bit is on
line 4. The attribute specifies that the fields of the class should be mapped sequentially to the struct on the other
(unmanaged) side. This means that the naming of the fields is not important, only their order is important, as it
needs to correspond to the unmanaged struct, shown below:

typedef struct _SYSTEMTIME {


WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME*;

We already saw the Linux and macOS example for this in the previous example. It is shown again below.
[StructLayout(LayoutKind.Sequential)]
public class StatClass {
public uint DeviceID;
public uint InodeNumber;
public uint Mode;
public uint HardLinks;
public uint UserID;
public uint GroupID;
public uint SpecialDeviceID;
public ulong Size;
public ulong BlockSize;
public uint Blocks;
public long TimeLastAccess;
public long TimeLastModification;
public long TimeLastStatusChange;
}

The StatClass class represents a structure that is returned by the stat system call on UNIX systems. It represents
information about a given file. The class above is the stat struct representation in managed code. Again, the fields
in the class have to be in the same order as the native struct (you can find these by perusing man pages on your
favorite UNIX implementation) and they have to be of the same underlying type.

More resources
PInvoke.net wiki an excellent Wiki with information on common Win32 APIs and how to call them.
P/Invoke on MSDN
Mono documentation on P/Invoke
Collections and Data Structures
7/29/2017 • 5 min to read • Edit Online

Similar data can often be handled more efficiently when stored and manipulated as a collection. You can use the
System.Array class or the classes in the System.Collections, System.Collections.Generic,
System.Collections.Concurrent, System.Collections.Immutable namespaces to add, remove, and modify either
individual elements or a range of elements in a collection.
There are two main types of collections; generic collections and non-generic collections. Generic collections were
added in the .NET Framework 2.0 and provide collections that are type-safe at compile time. Because of this,
generic collections typically offer better performance. Generic collections accept a type parameter when they are
constructed and do not require that you cast to and from the Object type when you add or remove items from the
collection. In addition, most generic collections are supported in Windows Store apps. Non-generic collections
store items as Object, require casting, and most are not supported for Windows Store app development. However,
you may see non-generic collections in older code.
Starting with the .NET Framework 4, the collections in the System.Collections.Concurrent namespace provide
efficient thread-safe operations for accessing collection items from multiple threads. The immutable collection
classes in the System.Collections.Immutable namespace (NuGet package) are inherently thread-safe because
operations are performed on a copy of the original collection and the original collection cannot be modified.

Common collection features


All collections provide methods for adding, removing or finding items in the collection. In addition, all collections
that directly or indirectly implement the ICollection interface or the ICollection<T> interface share these features:
The ability to enumerate the collection
.NET Framework collections either implement System.Collections.IEnumerable or
System.Collections.Generic.IEnumerable<T> to enable the collection to be iterated through. An enumerator
can be thought of as a movable pointer to any element in the collection. The foreach, in statement and the
For Each...Next Statement use the enumerator exposed by the GetEnumerator method and hide the
complexity of manipulating the enumerator. In addition, any collection that implements
System.Collections.Generic.IEnumerable<T> is considered a queryable type and can be queried with LINQ.
LINQ queries provide a common pattern for accessing data. They are typically more concise and readable
than standard foreach loops, and provide filtering, ordering and grouping capabilities. LINQ queries can
also improve performance. For more information, see LINQ to Objects, Parallel LINQ (PLINQ) and
Introduction to LINQ Queries (C#).
The ability to copy the collection contents to an array
All collections can be copied to an array using the CopyTo method; however, the order of the elements in
the new array is based on the sequence in which the enumerator returns them. The resulting array is always
one-dimensional with a lower bound of zero.
In addition, many collection classes contain the following features:
Capacity and Count properties
The capacity of a collection is the number of elements it can contain. The count of a collection is the number
of elements it actually contains. Some collections hide the capacity or the count or both.
Most collections automatically expand in capacity when the current capacity is reached. The memory is
reallocated, and the elements are copied from the old collection to the new one. This reduces the code
required to use the collection; however, the performance of the collection might be negatively affected. For
example, for List<T>, If Count is less than Capacity, adding an item is an O(1) operation. If the capacity needs
to be increased to accommodate the new element, adding an item becomes an O(n) operation, where n is
Count. The best way to avoid poor performance caused by multiple reallocations is to set the initial capacity
to be the estimated size of the collection.
A BitArray is a special case; its capacity is the same as its length, which is the same as its count.
A consistent lower bound
The lower bound of a collection is the index of its first element. All indexed collections in the
System.Collections namespaces have a lower bound of zero, meaning they are 0-indexed. Array has a lower
bound of zero by default, but a different lower bound can be defined when creating an instance of the Array
class using System.Array.CreateInstance.
Synchronization for access from multiple threads (System.Collections classes only).
Non-generic collection types in the System.Collections namespace provide some thread safety with
synchronization; typically exposed through the SyncRoot and IsSynchronized members. These collections
are not thread-safe by default. If you require scalable and efficient multi-threaded access to a collection, use
one of the classes in the System.Collections.Concurrent namespace or consider using an immutable
collection. For more information, see Thread-Safe Collections.

Choosing a collection
In general, you should use generic collections. The following table describes some common collection scenarios
and the collection classes you can use for those scenarios. If you are new to generic collections, this table will help
you choose the generic collection that works the best for your task.

GENERIC COLLECTION NON-GENERIC COLLECTION THREAD-SAFE OR IMMUTABLE


I WANT TO… OPTION(S) OPTION(S) COLLECTION OPTION(S)

Store items as key/value System.Collections.Generic.D Hashtable System.Collections.Concurre


pairs for quick look-up by ictionary<TKey,TValue> nt.ConcurrentDictionary<TK
key (A collection of key/value ey,TValue>
pairs that are organize based
on the hash code of the System.Collections.ObjectMo
key.) del.ReadOnlyDictionary<TKe
y,TValue>

ImmutableDictionary(TKey,
TValue) Class

Access items by index System.Collections.Generic.Li System.Array ImmutableList(T) Class


st<T>
System.Collections.ArrayList ImmutableArray Class

Use items first-in-first-out System.Collections.Generic.Q System.Collections.Queue System.Collections.Concurre


(FIFO) ueue<T> nt.ConcurrentQueue<T>

ImmutableQueue(T) Class

Use data Last-In-First-Out System.Collections.Generic.St System.Collections.Stack System.Collections.Concurre


(LIFO) ack<T> nt.ConcurrentStack<T>

ImmutableStack(T) Class
GENERIC COLLECTION NON-GENERIC COLLECTION THREAD-SAFE OR IMMUTABLE
I WANT TO… OPTION(S) OPTION(S) COLLECTION OPTION(S)

Access items sequentially System.Collections.Generic.Li No recommendation No recommendation


nkedList<T>

Receive notifications when System.Collections.ObjectMo No recommendation No recommendation


items are removed or added del.ObservableCollection<T>
to the collection.
(implements
INotifyPropertyChanged and
System.Collections.Specialize
d.INotifyCollectionChanged)

A sorted collection System.Collections.Generic.S System.Collections.SortedList ImmutableSortedDictionary(TKey,


ortedList<TKey,TValue> TValue) Class

ImmutableSortedSet(T)
Class

A set for mathematical System.Collections.Generic.H No recommendation ImmutableHashSet(T)


functions ashSet<T> Class

System.Collections.Generic.S ImmutableSortedSet(T)
Class
ortedSet<T>

Related Topics
TITLE DESCRIPTION

Selecting a Collection Class Describes the different collections and helps you select one for
your scenario.

Commonly Used Collection Types Describes commonly used generic and nongeneric collection
types such as System.Array,
System.Collections.Generic.List<T>, and
System.Collections.Generic.Dictionary<TKey,TValue>.

When to Use Generic Collections Discusses the use of generic collection types.

Comparisons and Sorts Within Collections Discusses the use of equality comparisons and sorting
comparisons in collections.

Sorted Collection Types Describes sorted collections performance and characteristics

Hashtable and Dictionary Collection Types Describes the features of generic and non-generic hash-based
dictionary types.

Thread-Safe Collections Describes collection types such as


System.Collections.Concurrent.BlockingCollection<T> and
System.Collections.Concurrent.ConcurrentBag<T> that
support safe and efficient concurrent access from multiple
threads.

System.Collections.Immutable Introduces the immutable collections and provides links to the


collection types.
Reference
System.Array
System.Collections
System.Collections.Concurrent
System.Collections.Generic
System.Collections.Specialized
System.Linq
System.Collections.Immutable
Numerics in the .NET Framework
7/29/2017 • 3 min to read • Edit Online

The .NET Framework supports the standard numeric integral and floating-point primitives, as well as BigInteger, an
integral type with no theoretical upper or lower bound, Complex, a type that represents complex numbers, and a
set of SIMD-enabled vector types in the System.Numerics namespace.
In addition, System.Numerics.Vectors, the SIMD-enabled library of vectory types, was released as a NuGet package.

Integral types
The .NET Framework supports both signed and unsigned integers ranging from one byte to eight bytes in length.
The following table lists the integral types and their size, indicates whether they are signed or unsigned, and
documents their range. All integers are value types.

TYPE SIGNED/UNSIGNED SIZE (BYTES) MINIMUM VALUE MAXIMUM VALUE

System.Byte Unsigned 1 0 255

System.Int16 Signed 2 -32,768 32,767

System.Int32 Signed 4 -2,147,483,648 2,147,483,647

System.Int64 Signed 8 - 9,223,372,036,854,77


9,223,372,036,854,77 5,807
5,808

System.SByte Signed 1 -128 127

System.UInt16 Unsigned 2 0 65,535

System.UInt32 Unsigned 4 0 4,294,967,295

System.UInt64 Unsigned 8 0 18,446,744,073,709,5


51,615

Each integral type supports a standard set of arithmetic, comparison, equality, explicit conversion, and implicit
conversion operators. Each integer also includes methods to perform equality comparisons and relative
comparisons, to convert the string representation of a number to that integer, and to convert an integer to its string
representation. Some additional mathematical operations beyond those handled by the standard operators, such as
rounding and identifying the smaller or larger value of two integers, are available from the Math class. You can also
work with the individual bits in an integer value by using the BitConverter class.
Note that the unsigned integral types are not CLS-compliant. For more information, see Language Independence
and Language-Independent Components.

Floating-point types
The .NET Framework includes three primitive floating point types, which are listed in the following table.
TYPE SIZE (IN BYTES) MINIMUM MAXIMUM

System.Double 8 -1.79769313486232e308 1.79769313486232e308

System.Single 4 -3.402823e38 3.402823e38

System.Decimal 16 - 79,228,162,514,264,337,593
79,228,162,514,264,337,59 ,543,950,335
3,543,950,335

Each floating-point type supports a standard set of arithmetic, comparison, equality, explicit conversion, and
implicit conversion operators. Each also includes methods to perform equality comparisons and relative
comparisons, to convert the string representation of a floating-point number, and to convert a floating-point
number to its string representation. Some additional mathematical, algebraic, and trigonometric operations are
available from the Math class. You can also work with the individual bits in Double and Single values by using the
BitConverter class. The System.Decimal structure has its own methods, System.Decimal.GetBits and
System.Decimal.Decimal(Int32[]), for working with a decimal value's individual bits, as well as its own set of
methods for performing some additional mathematical operations.
The Double and Single types are intended to be used for values that by their nature are imprecise (such as the
distance between two stars in the solar system) and for applications in which a high degree of precision and small
rounding error is not required. You should use the System.Decimal type for cases in which greater precision is
required and rounding error is undesirable,

BigInteger
System.Numerics.BigInteger is an immutable type that represents an arbitrarily large integer whose value in theory
has no upper or lower bounds. The methods of the BigInteger type closely parallel those of the other integral types.

Complex
The Complex type represents a complex number, that is, a number with a real number part and an imaginary
number part. It supports a standard set of arithmetic, comparison, equality, explicit conversion, and implicit
conversion operators, as well as mathematical, algebraic, and trigonometric methods.

SIMD-enabled vector types


The System.Numerics namespace includes a set of SIMD-enabled vector types for the .NET Framework. SIMD
(Single Instruction Multiple Data operations) allows some operations to be parallelized at the hardware level, which
results in huge performance improvements in mathematical, scientific, and graphics apps that perform
computations over vectors.
The SIMD-enabled vector types in the .NET Framework include the following: . In addition,
System.Numerics.Vectors includes a Plane type and a Quaternion type.
Vector2, Vector3, and Vector4 types, which are 2-, 3-, and 4-dimensional vectors of type Single.
Two matrix types, Matrix3x2, which represents a 3x2 matrix; and Matrix4x4, which represents a 4x4 matrix.
The Plane and Quaternion types.
The SimD-enabled vector types are implemented in IL, which allows them to be used on non-SimD-enabled
hardware and JIT compilers. To take advantage of SIMD instructions, your 64-bit apps must be compiled by the
new 64-bit JIT Compiler for managed code, which is included with the .NET Framework 4.6; it adds SIMD support
when targeting x64 processors.
SIMD can also be downloaded as a NuGet package. The NuGET package also includes a generic Vector<T>
structure that allows you to create a vector of any primitive numeric type. (The primitive numeric types include all
numeric types in the System namespace except for Decimal.) In addition, the Vector<T> structure provides a library
of convenience methods that you can call when working with vectors.

See Also
Application Essentials
Dates, times, and time zones
7/29/2017 • 2 min to read • Edit Online

In addition to the basic DateTime structure, .NET provides the following classes that support working with time
zones:
TimeZone
Use this class to work with the system's local time zone and the Coordinated Universal Time (UTC) zone.The
functionality of the TimeZone class is largely superseded by the TimeZoneInfo class.
TimeZoneInfo
Use this class to work with any time zone that is predefined on a system, to create new time zones, and to
easily convert dates and times from one time zone to another. For new development, use the TimeZoneInfo
class instead of the TimeZone class.
DateTimeOffset
Use this structure to work with dates and times whose offset (or difference) from UTC is known. The
DateTimeOffset structure combines a date and time value with that time's offset from UTC. Because of its
relationship to UTC, an individual date and time value unambiguously identifies a single point in time. This
makes a DateTimeOffset value more portable from one computer to another than a DateTime value.
This section of the documentation provides the information that you need to work with time zones and to create
time zone-aware applications that can convert dates and times from one time zone to another.

In this section
Time zone overview Discusses the terminology, concepts, and issues involved in creating time zone-aware
applications.
Choosing between DateTime, DateTimeOffset, TimeSpan, and TimeZoneInfo Discusses when to use the DateTime,
DateTimeOffset, and TimeZoneInfo types when working with date and time data.
Finding the time zones defined on a local system Describes how to enumerate the time zones found on a local
system.
How to: Enumerate time zones present on a computer Provides examples that enumerate the time zones defined in
a computer's registry and that let users select a predefined time zone from a list.
How to: Access the predefined UTC and local time zone objects Describes how to access Coordinated Universal
Time and the local time zone.
How to: Instantiate a TimeZoneInfo object Describes how to instantiate a TimeZoneInfo object from the local
system registry.
Instantiating a DateTimeOffset object Discusses the ways in which a DateTimeOffset object can be instantiated, and
the ways in which a DateTime value can be converted to a DateTimeOffset value.
How to: Create time zones without adjustment rules Describes how to create a custom time zone that does not
support the transition to and from daylight saving time.
How to: Create time zones with adjustment rules Describes how to create a custom time zone that supports one or
more transitions to and from daylight saving time.
Saving and restoring time zones Describes TimeZoneInfo support for serialization and deserialization of time zone
data and illustrates some of the scenarios in which these features can be used.
How to: Save time zones to an embedded resource Describes how to create a custom time zone and save its
information in a resource file.
How to: Restore time zones from an embedded resource Describes how to instantiate custom time zones that have
been saved to an embedded resource file.
Performing arithmetic operations with dates and times Discusses the issues involved in adding, subtracting, and
comparing DateTime and DateTimeOffset values.
How to: Use time zones in date and time arithmetic Discusses how to perform date and time arithmetic that reflects
a time zone's adjustment rules.
Converting between DateTime and DateTimeOffset Describes how to convert between DateTime and
DateTimeOffset values.
Converting times between time zones Describes how to convert times from one time zone to another.
How to: Resolve ambiguous times Describes how to resolve an ambiguous time by mapping it to the time zone's
standard time.
How to: Let users resolve ambiguous times Describes how to let a user determine the mapping between an
ambiguous local time and Coordinated Universal Time.

Reference
System.TimeZoneInfo
Handling and Raising Events
7/29/2017 • 7 min to read • Edit Online

Events in the .NET Framework are based on the delegate model. The delegate model follows the observer design
pattern, which enables a subscriber to register with, and receive notifications from, a provider. An event sender
pushes a notification that an event has happened, and an event receiver receives that notification and defines a
response to it. This article describes the major components of the delegate model, how to consume events in
applications, and how to implement events in your code.
For information about handling events in Windows 8.x Store apps, see Events and routed events overview
(Windows store apps).

Events
An event is a message sent by an object to signal the occurrence of an action. The action could be caused by user
interaction, such as a button click, or it could be raised by some other program logic, such as changing a property’s
value. The object that raises the event is called the event sender. The event sender doesn't know which object or
method will receive (handle) the events it raises. The event is typically a member of the event sender; for example,
the Click event is a member of the Button class, and the PropertyChanged event is a member of the class that
implements the INotifyPropertyChanged interface.
To define an event, you use the event (in C#) or Event (in Visual Basic) keyword in the signature of your event
class, and specify the type of delegate for the event. Delegates are described in the next section.
Typically, to raise an event, you add a method that is marked as protected and virtual (in C#) or Protected and
Overridable (in Visual Basic). Name this method On EventName; for example, OnDataReceived . The method
should take one parameter that specifies an event data object. You provide this method to enable derived classes
to override the logic for raising the event. A derived class should always call the On EventName method of the
base class to ensure that registered delegates receive the event.
The following example shows how to declare an event named ThresholdReached . The event is associated with the
EventHandler delegate and raised in a method named OnThresholdReached .

class Counter
{
public event EventHandler ThresholdReached;

protected virtual void OnThresholdReached(EventArgs e)


{
EventHandler handler = ThresholdReached;
if (handler != null)
{
handler(this, e);
}
}

// provide remaining implementation for the class


}
Public Class Counter
Public Event ThresholdReached As EventHandler

Protected Overridable Sub OnThresholdReached(e As EventArgs)


RaiseEvent ThresholdReached(Me, e)
End Sub

' provide remaining implementation for the class


End Class

Delegates
A delegate is a type that holds a reference to a method. A delegate is declared with a signature that shows the
return type and parameters for the methods it references, and can hold references only to methods that match its
signature. A delegate is thus equivalent to a type-safe function pointer or a callback. A delegate declaration is
sufficient to define a delegate class.
Delegates have many uses in the .NET Framework. In the context of events, a delegate is an intermediary (or
pointer-like mechanism) between the event source and the code that handles the event. You associate a delegate
with an event by including the delegate type in the event declaration, as shown in the example in the previous
section. For more information about delegates, see the Delegate class.
The .NET Framework provides the EventHandler and EventHandler<TEventArgs> delegates to support most event
scenarios. Use the EventHandler delegate for all events that do not include event data. Use the
EventHandler<TEventArgs> delegate for events that include data about the event. These delegates have no return
type value and take two parameters (an object for the source of the event and an object for event data).
Delegates are multicast, which means that they can hold references to more than one event-handling method. For
details, see the Delegate reference page. Delegates provide flexibility and fine-grained control in event handling. A
delegate acts as an event dispatcher for the class that raises the event by maintaining a list of registered event
handlers for the event.
For scenarios where the EventHandler and EventHandler<TEventArgs> delegates do not work, you can define a
delegate. Scenarios that require you to define a delegate are very rare, such as when you must work with code that
does not recognize generics. You mark a delegate with the delegate in (C#) and Delegate (in Visual Basic)
keyword in the declaration. The following example shows how to declare a delegate named
ThresholdReachedEventHandler .

public delegate void ThresholdReachedEventHandler(ThresholdReachedEventArgs e);

Public Delegate Sub ThresholdReachedEventHandler(e As ThresholdReachedEventArgs)

Event Data
Data that is associated with an event can be provided through an event data class. The .NET Framework provides
many event data classes that you can use in your applications. For example, the SerialDataReceivedEventArgs class
is the event data class for the System.IO.Ports.SerialPort.DataReceived event. The .NET Framework follows a
naming pattern of ending all event data classes with EventArgs . You determine which event data class is
associated with an event by looking at the delegate for the event. For example, the
SerialDataReceivedEventHandler delegate includes the SerialDataReceivedEventArgs class as one of its parameters.
The EventArgs class is the base type for all event data classes. EventArgs is also the class you use when an event
does not have any data associated with it. When you create an event that is only meant to notify other classes that
something happened and does not need to pass any data, include the EventArgs class as the second parameter in
the delegate. You can pass the System.EventArgs.Empty value when no data is provided. The EventHandler
delegate includes the EventArgs class as a parameter.
When you want to create a customized event data class, create a class that derives from EventArgs, and then
provide any members needed to pass data that is related to the event. Typically, you should use the same naming
pattern as the .NET Framework and end your event data class name with EventArgs .
The following example shows an event data class named ThresholdReachedEventArgs . It contains properties that are
specific to the event being raised.

public class ThresholdReachedEventArgs : EventArgs


{
public int Threshold { get; set; }
public DateTime TimeReached { get; set; }
}

Public Class ThresholdReachedEventArgs


Inherits EventArgs

Public Property Threshold As Integer


Public Property TimeReached As DateTime
End Class

Event Handlers
To respond to an event, you define an event handler method in the event receiver. This method must match the
signature of the delegate for the event you are handling. In the event handler, you perform the actions that are
required when the event is raised, such as collecting user input after the user clicks a button. To receive
notifications when the event occurs, your event handler method must subscribe to the event.
The following example shows an event handler method named c_ThresholdReached that matches the signature for
the EventHandler delegate. The method subscribes to the ThresholdReached event.

class Program
{
static void Main(string[] args)
{
Counter c = new Counter();
c.ThresholdReached += c_ThresholdReached;

// provide remaining implementation for the class


}

static void c_ThresholdReached(object sender, EventArgs e)


{
Console.WriteLine("The threshold was reached.");
}
}
Module Module1

Sub Main()
Dim c As Counter = New Counter()
AddHandler c.ThresholdReached, AddressOf c_ThresholdReached

' provide remaining implementation for the class


End Sub

Sub c_ThresholdReached(sender As Object, e As EventArgs)


Console.WriteLine("The threshold was reached.")
End Sub
End Module

Static and Dynamic Event Handlers


The .NET Framework allows subscribers to register for event notifications either statically or dynamically. Static
event handlers are in effect for the entire life of the class whose events they handle. Dynamic event handlers are
explicitly activated and deactivated during program execution, usually in response to some conditional program
logic. For example, they can be used if event notifications are needed only under certain conditions or if an
application provides multiple event handlers and run-time conditions define the appropriate one to use. The
example in the previous section shows how to dynamically add an event handler. For more information, see Events
and Events.

Raising Multiple Events


If your class raises multiple events, the compiler generates one field per event delegate instance. If the number of
events is large, the storage cost of one field per delegate may not be acceptable. For those situations, the .NET
Framework provides event properties that you can use with another data structure of your choice to store event
delegates.
Event properties consist of event declarations accompanied by event accessors. Event accessors are methods that
you define to add or remove event delegate instances from the storage data structure. Note that event properties
are slower than event fields, because each event delegate must be retrieved before it can be invoked. The trade-off
is between memory and speed. If your class defines many events that are infrequently raised, you will want to
implement event properties. For more information, see How to: Handle Multiple Events Using Event Properties.

Related Topics
TITLE DESCRIPTION

How to: Raise and Consume Events Contains examples of raising and consuming events.

How to: Handle Multiple Events Using Event Properties Shows how to use event properties to handle multiple events.

Observer Design Pattern Describes the design pattern that enables a subscriber to
register with, and receive notifications from, a provider.

How to: Consume Events in a Web Forms Application Shows how to handle an event that is raised by a Web Forms
control.

See Also
EventHandler
EventHandler<TEventArgs>
EventArgs
Delegate
Events and routed events overview (Windows store apps)
Events (Visual Basic)
Events (C# Programming Guide)
Managed Execution Process
7/29/2017 • 7 min to read • Edit Online

The managed execution process includes the following steps, which are discussed in detail later in this topic:
1. Choosing a compiler.
To obtain the benefits provided by the common language runtime, you must use one or more language
compilers that target the runtime.
2. Compiling your code to MSIL.
Compiling translates your source code into Microsoft intermediate language (MSIL) and generates the
required metadata.
3. Compiling MSIL to native code.
At execution time, a just-in-time (JIT) compiler translates the MSIL into native code. During this compilation,
code must pass a verification process that examines the MSIL and metadata to find out whether the code
can be determined to be type safe.
4. Running code.
The common language runtime provides the infrastructure that enables execution to take place and
services that can be used during execution.

Choosing a Compiler
To obtain the benefits provided by the common language runtime (CLR), you must use one or more language
compilers that target the runtime, such as Visual Basic, C#, Visual C++, F#, or one of many third-party compilers
such as an Eiffel, Perl, or COBOL compiler.
Because it is a multilanguage execution environment, the runtime supports a wide variety of data types and
language features. The language compiler you use determines which runtime features are available, and you
design your code using those features. Your compiler, not the runtime, establishes the syntax your code must use.
If your component must be completely usable by components written in other languages, your component's
exported types must expose only language features that are included in the Language Independence and
Language-Independent Components (CLS). You can use the CLSCompliantAttribute attribute to ensure that your
code is CLS-compliant. For more information, see Language Independence and Language-Independent
Components.
Back to top

Compiling to MSIL
When compiling to managed code, the compiler translates your source code into Microsoft intermediate language
(MSIL), which is a CPU-independent set of instructions that can be efficiently converted to native code. MSIL
includes instructions for loading, storing, initializing, and calling methods on objects, as well as instructions for
arithmetic and logical operations, control flow, direct memory access, exception handling, and other operations.
Before code can be run, MSIL must be converted to CPU-specific code, usually by a just-in-time (JIT) compiler.
Because the common language runtime supplies one or more JIT compilers for each computer architecture it
supports, the same set of MSIL can be JIT-compiled and run on any supported architecture.
When a compiler produces MSIL, it also produces metadata. Metadata describes the types in your code, including
the definition of each type, the signatures of each type's members, the members that your code references, and
other data that the runtime uses at execution time. The MSIL and metadata are contained in a portable executable
(PE) file that is based on and that extends the published Microsoft PE and common object file format (COFF) used
historically for executable content. This file format, which accommodates MSIL or native code as well as metadata,
enables the operating system to recognize common language runtime images. The presence of metadata in the
file together with MSIL enables your code to describe itself, which means that there is no need for type libraries or
Interface Definition Language (IDL). The runtime locates and extracts the metadata from the file as needed during
execution.
Back to top

Compiling MSIL to Native Code


Before you can run Microsoft intermediate language (MSIL), it must be compiled against the common language
runtime to native code for the target machine architecture. The .NET Framework provides two ways to perform
this conversion:
A .NET Framework just-in-time (JIT) compiler.
The .NET Framework Ngen.exe (Native Image Generator).
Compilation by the JIT Compiler
JIT compilation converts MSIL to native code on demand at application run time, when the contents of an
assembly are loaded and executed. Because the common language runtime supplies a JIT compiler for each
supported CPU architecture, developers can build a set of MSIL assemblies that can be JIT-compiled and run on
different computers with different machine architectures. However, if your managed code calls platform-specific
native APIs or a platform-specific class library, it will run only on that operating system.
JIT compilation takes into account the possibility that some code might never be called during execution. Instead
of using time and memory to convert all the MSIL in a PE file to native code, it converts the MSIL as needed during
execution and stores the resulting native code in memory so that it is accessible for subsequent calls in the context
of that process. The loader creates and attaches a stub to each method in a type when the type is loaded and
initialized. When a method is called for the first time, the stub passes control to the JIT compiler, which converts
the MSIL for that method into native code and modifies the stub to point directly to the generated native code.
Therefore, subsequent calls to the JIT-compiled method go directly to the native code.
Install-Time Code Generation Using NGen.exe
Because the JIT compiler converts an assembly's MSIL to native code when individual methods defined in that
assembly are called, it affects performance adversely at run time. In most cases, that diminished performance is
acceptable. More importantly, the code generated by the JIT compiler is bound to the process that triggered the
compilation. It cannot be shared across multiple processes. To allow the generated code to be shared across
multiple invocations of an application or across multiple processes that share a set of assemblies, the common
language runtime supports an ahead-of-time compilation mode. This ahead-of-time compilation mode uses the
Ngen.exe (Native Image Generator) to convert MSIL assemblies to native code much like the JIT compiler does.
However, the operation of Ngen.exe differs from that of the JIT compiler in three ways:
It performs the conversion from MSIL to native code before running the application instead of while the
application is running.
It compiles an entire assembly at a time, instead of one method at a time.
It persists the generated code in the Native Image Cache as a file on disk.
Code Verification
As part of its compilation to native code, the MSIL code must pass a verification process unless an administrator
has established a security policy that allows the code to bypass verification. Verification examines MSIL and
metadata to find out whether the code is type safe, which means that it accesses only the memory locations it is
authorized to access. Type safety helps isolate objects from each other and helps protect them from inadvertent or
malicious corruption. It also provides assurance that security restrictions on code can be reliably enforced.
The runtime relies on the fact that the following statements are true for code that is verifiably type safe:
A reference to a type is strictly compatible with the type being referenced.
Only appropriately defined operations are invoked on an object.
Identities are what they claim to be.
During the verification process, MSIL code is examined in an attempt to confirm that the code can access memory
locations and call methods only through properly defined types. For example, code cannot allow an object's fields
to be accessed in a manner that allows memory locations to be overrun. Additionally, verification inspects code to
determine whether the MSIL has been correctly generated, because incorrect MSIL can lead to a violation of the
type safety rules. The verification process passes a well-defined set of type-safe code, and it passes only code that
is type safe. However, some type-safe code might not pass verification because of some limitations of the
verification process, and some languages, by design, do not produce verifiably type-safe code. If type-safe code is
required by the security policy but the code does not pass verification, an exception is thrown when the code is
run.
Back to top

Running Code
The common language runtime provides the infrastructure that enables managed execution to take place and
services that can be used during execution. Before a method can be run, it must be compiled to processor-specific
code. Each method for which MSIL has been generated is JIT-compiled when it is called for the first time, and then
run. The next time the method is run, the existing JIT-compiled native code is run. The process of JIT-compiling and
then running the code is repeated until execution is complete.
During execution, managed code receives services such as garbage collection, security, interoperability with
unmanaged code, cross-language debugging support, and enhanced deployment and versioning support.
In Microsoft Windows XP and Windows Vista, the operating system loader checks for managed modules by
examining a bit in the COFF header. The bit being set denotes a managed module. If the loader detects managed
modules, it loads mscoree.dll, and _CorValidateImage and _CorImageUnloading notify the loader when the
managed module images are loaded and unloaded. _CorValidateImage performs the following actions:
1. Ensures that the code is valid managed code.
2. Changes the entry point in the image to an entry point in the runtime.
On 64-bit Windows, _CorValidateImage modifies the image that is in memory by transforming it from PE32 to
PE32+ format.
Back to top

See Also
Overview
Language Independence and Language-Independent Components
Metadata and Self-Describing Components
Ilasm.exe (IL Assembler)
Security
Interoperating with Unmanaged Code
Deployment
Assemblies in the Common Language Runtime
Application Domains
Metadata and Self-Describing Components
7/29/2017 • 8 min to read • Edit Online

In the past, a software component (.exe or .dll) that was written in one language could not easily use a software
component that was written in another language. COM provided a step towards solving this problem. The .NET
Framework makes component interoperation even easier by allowing compilers to emit additional declarative
information into all modules and assemblies. This information, called metadata, helps components to interact
seamlessly.
Metadata is binary information describing your program that is stored either in a common language runtime
portable executable (PE) file or in memory. When you compile your code into a PE file, metadata is inserted into
one portion of the file, and your code is converted to Microsoft intermediate language (MSIL) and inserted into
another portion of the file. Every type and member that is defined and referenced in a module or assembly is
described within metadata. When code is executed, the runtime loads metadata into memory and references it to
discover information about your code's classes, members, inheritance, and so on.
Metadata describes every type and member defined in your code in a language-neutral manner. Metadata stores
the following information:
Description of the assembly.
Identity (name, version, culture, public key).
The types that are exported.
Other assemblies that this assembly depends on.
Security permissions needed to run.
Description of types.
Name, visibility, base class, and interfaces implemented.
Members (methods, fields, properties, events, nested types).
Attributes.
Additional descriptive elements that modify types and members.

Benefits of Metadata
Metadata is the key to a simpler programming model, and eliminates the need for Interface Definition Language
(IDL) files, header files, or any external method of component reference. Metadata enables .NET Framework
languages to describe themselves automatically in a language-neutral manner, unseen by both the developer and
the user. Additionally, metadata is extensible through the use of attributes. Metadata provides the following major
benefits:
Self-describing files.
Common language runtime modules and assemblies are self-describing. A module's metadata contains
everything needed to interact with another module. Metadata automatically provides the functionality of IDL
in COM, so you can use one file for both definition and implementation. Runtime modules and assemblies
do not even require registration with the operating system. As a result, the descriptions used by the runtime
always reflect the actual code in your compiled file, which increases application reliability.
Language interoperability and easier component-based design.
Metadata provides all the information required about compiled code for you to inherit a class from a PE file
written in a different language. You can create an instance of any class written in any managed language
(any language that targets the common language runtime) without worrying about explicit marshaling or
using custom interoperability code.
Attributes.
The .NET Framework lets you declare specific kinds of metadata, called attributes, in your compiled file.
Attributes can be found throughout the .NET Framework and are used to control in more detail how your
program behaves at run time. Additionally, you can emit your own custom metadata into .NET Framework
files through user-defined custom attributes. For more information, see Attributes.

Metadata and the PE File Structure


Metadata is stored in one section of a .NET Framework portable executable (PE) file, while Microsoft intermediate
language (MSIL) is stored in another section of the PE file. The metadata portion of the file contains a series of table
and heap data structures. The MSIL portion contains MSIL and metadata tokens that reference the metadata
portion of the PE file. You might encounter metadata tokens when you use tools such as the MSIL Disassembler
(Ildasm.exe) to view your code's MSIL, for example.
Metadata Tables and Heaps
Each metadata table holds information about the elements of your program. For example, one metadata table
describes the classes in your code, another table describes the fields, and so on. If you have ten classes in your
code, the class table will have tens rows, one for each class. Metadata tables reference other tables and heaps. For
example, the metadata table for classes references the table for methods.
Metadata also stores information in four heap structures: string, blob, user string, and GUID. All the strings used to
name types and members are stored in the string heap. For example, a method table does not directly store the
name of a particular method, but points to the method's name stored in the string heap.
Metadata Tokens
Each row of each metadata table is uniquely identified in the MSIL portion of the PE file by a metadata token.
Metadata tokens are conceptually similar to pointers, persisted in MSIL, that reference a particular metadata table.
A metadata token is a four-byte number. The top byte denotes the metadata table to which a particular token refers
(method, type, and so on). The remaining three bytes specify the row in the metadata table that corresponds to the
programming element being described. If you define a method in C# and compile it into a PE file, the following
metadata token might exist in the MSIL portion of the PE file:

0x06000004

The top byte ( 0x06 ) indicates that this is a MethodDef token. The lower three bytes ( 000004 ) tells the common
language runtime to look in the fourth row of the MethodDef table for the information that describes this method
definition.
Metadata within a PE File
When a program is compiled for the common language runtime, it is converted to a PE file that consists of three
parts. The following table describes the contents of each part.

PE SECTION CONTENTS OF PE SECTION


PE SECTION CONTENTS OF PE SECTION

PE header The index of the PE file's main sections and the address of the
entry point.

The runtime uses this information to identify the file as a PE


file and to determine where execution starts when loading the
program into memory.

MSIL instructions The Microsoft intermediate language instructions (MSIL) that


make up your code. Many MSIL instructions are accompanied
by metadata tokens.

Metadata Metadata tables and heaps. The runtime uses this section to
record information about every type and member in your
code. This section also includes custom attributes and security
information.

Run-Time Use of Metadata


To better understand metadata and its role in the common language runtime, it might be helpful to construct a
simple program and illustrate how metadata affects its run-time life. The following code example shows two
methods inside a class called MyApp . The Main method is the program entry point, while the Add method simply
returns the sum of two integer arguments.

Public Class MyApp


Public Shared Sub Main()
Dim ValueOne As Integer = 10
Dim ValueTwo As Integer = 20
Console.WriteLine("The Value is: {0}", Add(ValueOne, ValueTwo))
End Sub

Public Shared Function Add(One As Integer, Two As Integer) As Integer


Return (One + Two)
End Function
End Class

using System;
public class MyApp
{
public static int Main()
{
int ValueOne = 10;
int ValueTwo = 20;
Console.WriteLine("The Value is: {0}", Add(ValueOne, ValueTwo));
return 0;
}
public static int Add(int One, int Two)
{
return (One + Two);
}
}

When the code runs, the runtime loads the module into memory and consults the metadata for this class. Once
loaded, the runtime performs extensive analysis of the method's Microsoft intermediate language (MSIL) stream to
convert it to fast native machine instructions. The runtime uses a just-in-time (JIT) compiler to convert the MSIL
instructions to native machine code one method at a time as needed.
The following example shows part of the MSIL produced from the previous code's Main function. You can view the
MSIL and metadata from any .NET Framework application using the MSIL Disassembler (Ildasm.exe).

.entrypoint
.maxstack 3
.locals ([0] int32 ValueOne,
[1] int32 ValueTwo,
[2] int32 V_2,
[3] int32 V_3)
IL_0000: ldc.i4.s 10
IL_0002: stloc.0
IL_0003: ldc.i4.s 20
IL_0005: stloc.1
IL_0006: ldstr "The Value is: {0}"
IL_000b: ldloc.0
IL_000c: ldloc.1
IL_000d: call int32 ConsoleApplication.MyApp::Add(int32,int32) /* 06000003 */

The JIT compiler reads the MSIL for the whole method, analyzes it thoroughly, and generates efficient native
instructions for the method. At IL_000d , a metadata token for the Add method ( /* 06000003 */ ) is encountered
and the runtime uses the token to consult the third row of the MethodDef table.
The following table shows part of the MethodDef table referenced by the metadata token that describes the Add
method. While other metadata tables exist in this assembly and have their own unique values, only this table is
discussed.

NAME
SIGNATURE
RELATIVE VIRTUAL (POINTS TO (POINTS TO BLOB
ROW ADDRESS (RVA) IMPLFLAGS FLAGS STRING HEAP.) HEAP.)

1 0x00002050 IL Public .ctor (constructor)

Managed ReuseSlot

SpecialName

RTSpecialName

.ctor

2 0x00002058 IL Public Main String

Managed Static

ReuseSlot

3 0x0000208c IL Public Add int, int, int

Managed Static

ReuseSlot

Each column of the table contains important information about your code. The RVA column allows the runtime to
calculate the starting memory address of the MSIL that defines this method. The ImplFlags and Flags columns
contain bitmasks that describe the method (for example, whether the method is public or private). The Name
column indexes the name of the method from the string heap. The Signature column indexes the definition of the
method's signature in the blob heap.
The runtime calculates the desired offset address from the RVA column in the third row and returns this address to
the JIT compiler, which then proceeds to the new address. The JIT compiler continues to process MSIL at the new
address until it encounters another metadata token and the process is repeated.
Using metadata, the runtime has access to all the information it needs to load your code and process it into native
machine instructions. In this manner, metadata enables self-describing files and, together with the common type
system, cross-language inheritance.

Related Topics
TITLE DESCRIPTION

Attributes Describes how to apply attributes, write custom attributes,


and retrieve information that is stored in attributes.
Building Console Applications in the .NET Framework
7/29/2017 • 1 min to read • Edit Online

Applications in the .NET Framework can use the System.Console class to read characters from and write characters
to the console. Data from the console is read from the standard input stream, data to the console is written to the
standard output stream, and error data to the console is written to the standard error output stream. These streams
are automatically associated with the console when the application starts and are presented as the In, Out, and
Error properties, respectively.
The value of the System.Console.In property is a System.IO.TextReader object, whereas the values of the
System.Console.Out and System.Console.Error properties are System.IO.TextWriter objects. You can associate these
properties with streams that do not represent the console, making it possible for you to point the stream to a
different location for input or output. For example, you can redirect the output to a file by setting the
System.Console.Out property to a System.IO.StreamWriter, which encapsulates a System.IO.FileStream by means of
the System.Console.SetOut method. The System.Console.In and System.Console.Out properties do not need to refer
to the same stream.

NOTE
For more information about building console applications, including examples in C#, Visual Basic, and C++, see the
documentation for the Console class.

If the console does not exist, as in a Windows-based application, output written to the standard output stream will
not be visible, because there is no console to write the information to. Writing information to an inaccessible
console does not cause an exception to be raised.
Alternately, to enable the console for reading and writing within a Windows-based application that is developed
using Visual Studio, open the project's Properties dialog box, click the Application tab, and set the Application
type to Console Application.
Console applications lack a message pump that starts by default. Therefore, console calls to Microsoft Win32 timers
might fail.
The System.Console class has methods that can read individual characters or entire lines from the console. Other
methods convert data and format strings, and then write the formatted strings to the console. For more
information on formatting strings, see Formatting Types.

See Also
System.Console
Formatting Types
Parallel Processing and Concurrency in the .NET
Framework
7/29/2017 • 1 min to read • Edit Online

The .NET Framework provides several ways for you to use multiple threads of execution to keep your application
responsive to your user while maximizing the performance of your user's computer.

In This Section
Threading
Describes the basic concurrency and synchronization mechanisms provided by the .NET Framework.
Asynchronous Programming Patterns
Provides a brief overview of the three asynchronous programming patterns supported in the .NET Framework:
Asynchronous Programming Model (APM) (legacy)
Event-based Asynchronous Pattern (EAP) (legacy)
Task-based Asynchronous Pattern (TAP) (recommended for new development)
Parallel Programming
Describes a task-based programming model that simplifies parallel development, enabling you to write efficient,
fine-grained, and scalable parallel code in a natural idiom without having to work directly with threads or the
thread pool.

See Also
Development Guide
.NET Framework Application Essentials
8/4/2017 • 1 min to read • Edit Online

This section of the .NET Framework documentation provides information about basic application development
tasks in the .NET Framework.

In This Section
Base Types
Discusses formatting and parsing base data types and using regular expressions to process text.
Collections and Data Structures
Discusses the various collection types available in the .NET Framework, including stacks, queues, lists, arrays, and
structs.
Generics
Describes the Generics feature, including the generic collections, delegates, and interfaces provided by the .NET
Framework. Provides links to feature documentation for C#, Visual Basic and Visual C++, and to supporting
technologies such as Reflection.
Numerics
Describes the numeric types in the .NET Framework.
Events
Provides an overview of the event model in the .NET Framework.
Exceptions
Describes error handling provided by the .NET Framework and the fundamentals of handling exceptions.
File and Stream I-O
Explains how you can perform synchronous and asynchronous file and data stream access and how to use to
isolated storage.
Dates, Times, and Time Zones
Describes how to work with time zones and time zone conversions in time zone-aware applications.
Application Domains and Assemblies
Describes how to create and work with assemblies and application domains.
Serialization
Discusses the process of converting the state of an object into a form that can be persisted or transported.
Resources in Desktop Apps
Describes the .NET Framework support for creating and storing resources. This section also describes support for
localized resources and the satellite assembly resource model for packaging and deploying those localized
resources.
Globalization and Localization
Provides information to help you design and develop world-ready applications.
Accessibility
Provides information about Microsoft UI Automation, which is an accessibility framework that addresses the needs
of assistive technology products and automated test frameworks by providing programmatic access to information
about the user interface (UI).
Attributes
Describes how you can use attributes to customize metadata.
64-bit Applications
Discusses issues relevant to developing applications that will run on a Windows 64-bit operating system.

Related Sections
Development Guide
Provides a guide to all key technology areas and tasks for application development, including creating, configuring,
debugging, securing, and deploying your application, and information about dynamic programming,
interoperability, extensibility, memory management, and threading.
Security
Provides information about the classes and services in the common language runtime and the .NET Framework
that facilitate secure application development.
File and Stream I/O
7/29/2017 • 7 min to read • Edit Online

File and stream I/O (input/output) refers to the transfer of data either to or from a storage medium. In the .NET
Framework, the System.IO namespaces contain types that enable reading and writing, both synchronously and
asynchronously, on data streams and files. These namespaces also contain types that perform compression and
decompression on files, and types that enable communication through pipes and serial ports.
A file is an ordered and named collection of bytes that has persistent storage. When you work with files, you work
with directory paths, disk storage, and file and directory names. In contrast, a stream is a sequence of bytes that
you can use to read from and write to a backing store, which can be one of several storage mediums (for example,
disks or memory). Just as there are several backing stores other than disks, there are several kinds of streams other
than file streams, such as network, memory, and pipe streams.

Files and Directories


You can use the types in the System.IO namespace to interact with files and directories. For example, you can get
and set properties for files and directories, and retrieve collections of files and directories based on search criteria.
Here are some commonly used file and directory classes:
File - provides static methods for creating, copying, deleting, moving, and opening files, and helps create a
FileStream object.
FileInfo - provides instance methods for creating, copying, deleting, moving, and opening files, and helps
create a FileStream object.
Directory - provides static methods for creating, moving, and enumerating through directories and
subdirectories.
DirectoryInfo - provides instance methods for creating, moving, and enumerating through directories and
subdirectories.
Path - provides methods and properties for processing directory strings in a cross-platform manner.
In addition to using these classes, Visual Basic users can use the methods and properties provided by the
Microsoft.VisualBasic.FileIO.FileSystem class for file I/O.
See How to: Copy Directories, How to: Create a Directory Listing, and How to: Enumerate Directories and Files.

Streams
The abstract base class Stream supports reading and writing bytes. All classes that represent streams inherit from
the Stream class. The Stream class and its derived classes provide a common view of data sources and repositories,
and isolate the programmer from the specific details of the operating system and underlying devices.
Streams involve three fundamental operations:
Reading - transferring data from a stream into a data structure, such as an array of bytes.
Writing - transferring data to a stream from a data source.
Seeking - querying and modifying the current position within a stream.
Depending on the underlying data source or repository, a stream might support only some of these capabilities.
For example, the PipeStream class does not support seeking. The CanRead, CanWrite, and CanSeek properties of a
stream specify the operations that the stream supports.
Here are some commonly used stream classes:
FileStream – for reading and writing to a file.
IsolatedStorageFileStream – for reading and writing to a file in isolated storage.
MemoryStream – for reading and writing to memory as the backing store.
BufferedStream – for improving performance of read and write operations.
NetworkStream – for reading and writing over network sockets.
PipeStream – for reading and writing over anonymous and named pipes.
CryptoStream – for linking data streams to cryptographic transformations.
For an example of working with streams asynchronously, see Asynchronous File I/O.

Readers and Writers


The System.IO namespace also provides types for reading encoded characters from streams and writing them to
streams. Typically, streams are designed for byte input and output. The reader and writer types handle the
conversion of the encoded characters to and from bytes so the stream can complete the operation. Each reader and
writer class is associated with a stream, which can be retrieved through the class's BaseStream property.
Here are some commonly used reader and writer classes:
BinaryReader and BinaryWriter – for reading and writing primitive data types as binary values.
StreamReader and StreamWriter – for reading and writing characters by using an encoding value to convert
the characters to and from bytes.
StringReader and StringWriter – for reading and writing characters to and from strings.
TextReader and TextWriter – serve as the abstract base classes for other readers and writers that read and
write characters and strings, but not binary data.
See How to: Read Text from a File, How to: Write Text to a File, How to: Read Characters from a String, and How to:
Write Characters to a String.

Asynchronous I/O Operations


Reading or writing a large amount of data can be resource-intensive. You should perform these tasks
asynchronously if your application needs to remain responsive to the user. With synchronous I/O operations, the
UI thread is blocked until the resource-intensive operation has completed. Use asynchronous I/O operations when
developing Windows 8.x Store apps to prevent creating the impression that your app has stopped working.
The asynchronous members contain Async in their names, such as the CopyToAsync, FlushAsync, ReadAsync, and
WriteAsync methods. You use these methods with the async and await keywords.
For more information, see Asynchronous File I/O.

Compression
Compression refers to the process of reducing the size of a file for storage. Decompression is the process of
extracting the contents of a compressed file so they are in a usable format. The System.IO.Compression namespace
contains types for compressing and decompressing files and streams.
The following classes are frequently used when compressing and decompressing files and streams:
ZipArchive – for creating and retrieving entries in the zip archive.
ZipArchiveEntry – for representing a compressed file.
ZipFile – for creating, extracting, and opening a compressed package.
ZipFileExtensions – for creating and extracting entries in a compressed package.
DeflateStream – for compressing and decompressing streams using the Deflate algorithm.
GZipStream – for compressing and decompressing streams in gzip data format.
See How to: Compress and Extract Files.

Isolated Storage
Isolated storage is a data storage mechanism that provides isolation and safety by defining standardized ways of
associating code with saved data. The storage provides a virtual file system that is isolated by user, assembly, and
(optionally) domain. Isolated storage is particularly useful when your application does not have permission to
access user files. You can save settings or files for your application in a manner that is controlled by the computer's
security policy.
Isolated storage is not available for Windows 8.x Store apps; instead, use application data classes in the
Windows.Storage namespace. For more information, see Application data in the Windows Dev Center.
The following classes are frequently used when implementing isolated storage:
IsolatedStorage – provides the base class for isolated storage implementations.
IsolatedStorageFile – provides an isolated storage area that contains files and directories.
IsolatedStorageFileStream - exposes a file within isolated storage.
See Isolated Storage.

I/O Operations in Windows Store apps


The .NET for Windows 8.x Store apps contains many of the types for reading from and writing to streams; however,
this set does not include all the .NET Framework I/O types.
Some important differences to note when using I/O operations in Windows 8.x Store apps:
Types specifically related to file operations, such as File, FileInfo, Directory and DirectoryInfo, are not
included in the .NET for Windows 8.x Store apps. Instead, use the types in the Windows.Storage namespace
of the Windows Runtime, such as StorageFile and StorageFolder.
Isolated storage is not available; instead, use application data.
Use asynchronous methods, such as ReadAsync and WriteAsync, to prevent blocking the UI thread.
The path-based compression types ZipFile and ZipFileExtensions are not available. Instead, use the types in
the Windows.Storage.Compression namespace.
You can convert between .NET Framework streams and Windows Runtime streams, if necessary. For more
information, see How to: Convert Between .NET Framework Streams and Windows Runtime Streams or
System.IO.WindowsRuntimeStreamExtensions.
For more information about I/O operations in a Windows 8.x Store app, see Quickstart: Reading and writing a file
in the Windows Dev Center.
I/O and Security
When you use the classes in the System.IO namespace, you must follow operating system security requirements
such as access control lists (ACLs) to control access to files and directories. This requirement is in addition to any
FileIOPermission requirements. You can manage ACLs programmatically. For more information, see How to: Add
or Remove Access Control List Entries.
Default security policies prevent Internet or intranet applications from accessing files on the user’s computer.
Therefore, do not use the I/O classes that require a path to a physical file when writing code that will be
downloaded over the Internet or intranet. Instead, use isolated storage for traditional .NET Framework applications,
or use application data for Windows 8.x Store apps.
A security check is performed only when the stream is constructed. Therefore, do not open a stream and then pass
it to less-trusted code or application domains.

Related Topics
Common I/O Tasks
Provides a list of I/O tasks associated with files, directories, and streams, and links to relevant content and examples
for each task.
Asynchronous File I/O
Describes the performance advantages and basic operation of asynchronous I/O.
Isolated Storage
Describes a data storage mechanism that provides isolation and safety by defining standardized ways of
associating code with saved data.
Pipes
Describes anonymous and named pipe operations in the .NET Framework.
Memory-Mapped Files
Describes memory-mapped files, which contain the contents of files on disk in virtual memory. You can use
memory-mapped files to edit very large files and to create shared memory for interprocess communication.
Globalizing and Localizing .NET Framework
Applications
7/29/2017 • 2 min to read • Edit Online

Developing a world-ready application, including an application that can be localized into one or more languages,
involves three steps: globalization, localizability review, and localization.
Globalization
This step involves designing and coding an application that is culture-neutral and language-neutral, and that
supports localized user interfaces and regional data for all users. It involves making design and programming
decisions that are not based on culture-specific assumptions. While a globalized application is not localized, it
nevertheless is designed and written so that it can be subsequently localized into one or more languages with
relative ease.
Localizability Review
This step involves reviewing an application's code and design to ensure that it can be localized easily and to
identify potential roadblocks for localization, and verifying that the application's executable code is separated from
its resources. If the globalization stage was effective, the localizability review will confirm the design and coding
choices made during globalization. The localizability stage may also identify any remaining issues so that an
application's source code doesn't have to be modified during the localization stage.
Localization
This step involves customizing an application for specific cultures or regions. If the globalization and localizability
steps have been performed correctly, localization consists primarily of translating the user interface.
Following these three steps provides two advantages:
It frees you from having to retrofit an application that is designed to support a single culture, such as U.S.
English, to support additional cultures.
It results in localized applications that are more stable and have fewer bugs.
The .NET Framework provides extensive support for the development of world-ready and localized applications. In
particular, many type members in the .NET Framework class library aid globalization by returning values that
reflect the conventions of either the current user's culture or a specified culture. Also, the .NET Framework supports
satellite assemblies, which facilitate the process of localizing an application.
For additional information, see the Go Global Developer Center.

In This Section
Globalization
Discusses the first stage of creating a world-ready application, which involves designing and coding an application
that is culture-neutral and language-neutral.
Localizability Review
Discusses the second stage of creating a localized application, which involves identifying potential roadblocks to
localization.
Localization
Discusses the final stage of creating a localized application, which involves customizing an application's user
interface for specific regions or cultures.
Culture-Insensitive String Operations
Describes how to use .NET Framework methods and classes that are culture-sensitive by default to obtain culture-
insensitive results.
Best Practices for Developing World-Ready Applications
Describes the best practices to follow for globalization, localization, and developing world-ready ASP.NET
applications.

Reference
System.Globalization namespace
Contains classes that define culture-related information, including the language, the country/region, the calendars
in use, the format patterns for dates, currency, and numbers, and the sort order for strings.
System.Resources namespace
Provides classes for creating, manipulating, and using resources.
System.Text namespace
Contains classes representing ASCII, ANSI, Unicode, and other character encodings.
Resgen.exe (Resource File Generator)
Describes how to use Resgen.exe to convert .txt files and XML-based resource format (.resx) files to common
language runtime binary .resources files.
Winres.exe (Windows Forms Resource Editor)
Describes how to use Winres.exe to localize Windows Forms forms.
Extending Metadata Using Attributes
7/29/2017 • 1 min to read • Edit Online

The common language runtime allows you to add keyword-like descriptive declarations, called attributes, to
annotate programming elements such as types, fields, methods, and properties. When you compile your code for
the runtime, it is converted into Microsoft intermediate language (MSIL) and placed inside a portable executable
(PE) file along with metadata generated by the compiler. Attributes allow you to place extra descriptive information
into metadata that can be extracted using runtime reflection services. The compiler creates attributes when you
declare instances of special classes that derive from System.Attribute.
The .NET Framework uses attributes for a variety of reasons and to address a number of issues. Attributes describe
how to serialize data, specify characteristics that are used to enforce security, and limit optimizations by the just-
in-time (JIT) compiler so the code remains easy to debug. Attributes can also record the name of a file or the
author of code, or control the visibility of controls and members during forms development.

Related Topics
TITLE DESCRIPTION

Applying Attributes Describes how to apply an attribute to an element of your


code.

Writing Custom Attributes Describes how to design custom attribute classes.

Retrieving Information Stored in Attributes Describes how to retrieve custom attributes for code that is
loaded into the execution context.

Metadata and Self-Describing Components Provides an overview of metadata and describes how it is
implemented in a .NET Framework portable executable (PE)
file.

How to: Load Assemblies into the Reflection-Only Context Explains how to retrieve custom attribute information in the
reflection-only context.

Reference
System.Attribute
Framework Design Guidelines
7/29/2017 • 1 min to read • Edit Online

This section provides guidelines for designing libraries that extend and interact with the .NET Framework. The goal
is to help library designers ensure API consistency and ease of use by providing a unified programming model that
is independent of the programming language used for development. We recommend that you follow these design
guidelines when developing classes and components that extend the .NET Framework. Inconsistent library design
adversely affects developer productivity and discourages adoption.
The guidelines are organized as simple recommendations prefixed with the terms Do , Consider , Avoid , and
Do not . These guidelines are intended to help class library designers understand the trade-offs between different
solutions. There might be situations where good library design requires that you violate these design guidelines.
Such cases should be rare, and it is important that you have a clear and compelling reason for your decision.
These guidelines are excerpted from the book Framework Design Guidelines: Conventions, Idioms, and Patterns for
Reusable .NET Libraries, 2nd Edition, by Krzysztof Cwalina and Brad Abrams.

In This Section
Naming Guidelines
Provides guidelines for naming assemblies, namespaces, types, and members in class libraries.
Type Design Guidelines
Provides guidelines for using static and abstract classes, interfaces, enumerations, structures, and other types.
Member Design Guidelines
Provides guidelines for designing and using properties, methods, constructors, fields, events, operators, and
parameters.
Designing for Extensibility
Discusses extensibility mechanisms such as subclassing, using events, virtual members, and callbacks, and explains
how to choose the mechanisms that best meet your framework's requirements.
Design Guidelines for Exceptions
Describes design guidelines for designing, throwing, and catching exceptions.
Usage Guidelines
Describes guidelines for using common types such as arrays, attributes, and collections, supporting serialization,
and overloading equality operators.
Common Design Patterns
Provides guidelines for choosing and implementing dependency properties and the dispose pattern.
Portions © 2005, 2009 Microsoft Corporation. All rights reserved.
Reprinted by permission of Pearson Education, Inc. from Framework Design Guidelines: Conventions, Idioms, and
Patterns for Reusable .NET Libraries, 2nd Edition by Krzysztof Cwalina and Brad Abrams, published Oct 22, 2008 by
Addison-Wesley Professional as part of the Microsoft Windows Development Series.

See Also
Overview
Roadmap for the .NET Framework
Development Guide
XML Documents and Data
7/29/2017 • 2 min to read • Edit Online

The .NET Framework provides a comprehensive and integrated set of classes that enable you to build XML-aware
apps easily. The classes in the following namespaces support parsing and writing XML, editing XML data in
memory, data validation, and XSLT transformation.
System.Xml
System.Xml.XPath
System.Xml.Xsl
System.Xml.Schema
System.Xml.Linq
For a full list, see the System.Xml Namespaces webpage.
The classes in these namespaces support World Wide Web Consortium (W3C) recommendations. For example:
The System.Xml.XmlDocument class implements the W3C Document Object Model (DOM) Level 1 Core and
DOM Level 2 Core recommendations.
The System.Xml.XmlReader and System.Xml.XmlWriter classes support the W3C XML 1.0 and the
Namespaces in XML recommendations.
Schemas in the System.Xml.Schema.XmlSchemaSet class support the W3C XML Schema Part 1: Structures
and XML Schema Part 2: Datatypes recommendations.
Classes in the System.Xml.Xsl namespace support XSLT transformations that conform to the W3C XSLT 1.0
recommendation.
The XML classes in the .NET Framework provide these benefits:
Productivity. LINQ to XML makes it easier to program with XML and provides a query experience that is
similar to SQL.
Extensibility. The XML classes in the .NET Framework are extensible through the use of abstract base
classes and virtual methods. For example, you can create a derived class of the XmlUrlResolver class that
stores the cache stream to the local disk.
Pluggable architecture. The .NET Framework provides an architecture in which components can utilize
one another, and data can be streamed between components. For example, a data store, such as an
XPathDocument or XmlDocument object, can be transformed with the XslCompiledTransform class, and the
output can then be streamed either into another store or returned as a stream from a web service.
Performance. For better app performance, some of the XML classes in the .NET Framework support a
streaming-based model with the following characteristics:
Minimal caching for forward-only, pull-model parsing (XmlReader).
Forward-only validation (XmlReader).
Cursor style navigation that minimizes node creation to a single virtual node while providing random
access to the document (XPathNavigator).
For better performance whenever XSLT processing is required, you can use the XPathDocument class, which
is an optimized, read-only store for XPath queries designed to work efficiently with the
XslCompiledTransform class.
Integration with ADO.NET. The XML classes and ADO.NET are tightly integrated to bring together
relational data and XML. The DataSet class is an in-memory cache of data retrieved from a database. The
DataSet class has the ability to read and write XML by using the XmlReader and XmlWriter classes, to persist
its internal relational schema structure as XML schemas (XSD), and to infer the schema structure of an XML
document.

In This Section
XML Processing Options
Discusses options for processing XML data.
Processing XML Data In-Memory
Discusses the three models for processing XML data in-memory. LINQ to XML, the XmlDocument class (based on
the W3C Document Object Model), and the XPathDocument class (based on the XPath data model).
XSLT Transformations
Describes how to use the XSLT processor.
XML Schema Object Model (SOM)
Describes the classes used for building and manipulating XML Schemas (XSD) by providing an XmlSchema class to
load and edit a schema.
XML Integration with Relational Data and ADO.NET
Describes how the .NET Framework enables real-time, synchronous access to both the relational and hierarchical
representations of data through the DataSet object and the XmlDataDocument object.
Managing Namespaces in an XML Document
Describes how the XmlNamespaceManager class is used to store and maintain namespace information.
Type Support in the System.Xml Classes
Describes how XML data types map to CLR types, how to convert XML data types, and other type support features
in the System.Xml classes.

Related Sections
ADO.NET
Provides information on how to access data using ADO.NET.
Security
Provides an overview of the .NET Framework security system.
XML Developer Center
Provides additional technical information, downloads, newsgroups, and other resources for XML developers.
Managed Threading
7/29/2017 • 1 min to read • Edit Online

Whether you are developing for computers with one processor or several, you want your application to provide the
most responsive interaction with the user, even if the application is currently doing other work. Using multiple
threads of execution is one of the most powerful ways to keep your application responsive to the user and at the
same time make use of the processor in between or even during user events. While this section introduces the
basic concepts of threading, it focuses on managed threading concepts and using managed threading.

NOTE
Starting with the .NET Framework 4, multithreaded programming is greatly simplified with the
System.Threading.Tasks.Parallel and System.Threading.Tasks.Task classes, Parallel LINQ (PLINQ), new concurrent collection
classes in the System.Collections.Concurrent namespace, and a new programming model that is based on the concept of
tasks rather than threads. For more information, see Parallel Programming.

In This Section
Managed Threading Basics
Provides an overview of managed threading and discusses when to use multiple threads.
Using Threads and Threading
Explains how to create, start, pause, resume, and abort threads.
Managed Threading Best Practices
Discusses levels of synchronization, how to avoid deadlocks and race conditions, single-processor and
multiprocessor computers, and other threading issues.
Threading Objects and Features
Describes the managed classes you can use to synchronize the activities of threads and the data of objects accessed
on different threads, and provides an overview of thread pool threads.

Reference
System.Threading
Contains classes for using and synchronizing managed threads.
System.Collections.Concurrent
Contains collection classes that are safe for use with multiple threads.
System.Threading.Tasks
Contains classes for creating and scheduling concurrent processing tasks.

Related Sections
Application Domains
Provides an overview of application domains and their use by the Common Language Infrastructure.
Asynchronous File I/O
Describes the performance advantages and basic operation of asynchronous I/O.
Event-based Asynchronous Pattern (EAP)
Provides an overview of asynchronous programming.
Calling Synchronous Methods Asynchronously
Explains how to call methods on thread pool threads using built-in features of delegates.
Parallel Programming
Describes the parallel programming libraries, which simplify the use of multiple threads in applications.
Parallel LINQ (PLINQ)
Describes a system for running queries in parallel, to take advantage of multiple processors.
Parallel Programming in the .NET Framework
7/29/2017 • 1 min to read • Edit Online

Many personal computers and workstations have two or four cores (that is, CPUs) that enable multiple threads to
be executed simultaneously. Computers in the near future are expected to have significantly more cores. To take
advantage of the hardware of today and tomorrow, you can parallelize your code to distribute work across multiple
processors. In the past, parallelization required low-level manipulation of threads and locks. Visual Studio 2010 and
the .NET Framework 4 enhance support for parallel programming by providing a new runtime, new class library
types, and new diagnostic tools. These features simplify parallel development so that you can write efficient, fine-
grained, and scalable parallel code in a natural idiom without having to work directly with threads or the thread
pool. The following illustration provides a high-level overview of the parallel programming architecture in the .NET
Framework 4.

Related Topics
TECHNOLOGY DESCRIPTION

Task Parallel Library (TPL) Provides documentation for the


System.Threading.Tasks.Parallel class, which includes parallel
versions of For and ForEach loops, and also for the
System.Threading.Tasks.Task class, which represents the
preferred way to express asynchronous operations.

Parallel LINQ (PLINQ) A parallel implementation of LINQ to Objects that significantly


improves performance in many scenarios.

Data Structures for Parallel Programming Provides links to documentation for thread-safe collection
classes, lightweight synchronization types, and types for lazy
initialization.

Parallel Diagnostic Tools Provides links to documentation for Visual Studio debugger
windows for tasks and parallel stacks, and the Concurrency
Visualizer, which consists of a set of views in the Visual Studio
Application Lifecycle Management Profiler that you can use to
debug and to tune the performance of parallel code.
TECHNOLOGY DESCRIPTION

Custom Partitioners for PLINQ and TPL Describes how partitioners work and how to configure the
default partitioners or create a new partitioner.

Task Schedulers Describes how schedulers work and how the default
schedulers may be configured.

Lambda Expressions in PLINQ and TPL Provides a brief overview of lambda expressions in C# and
Visual Basic, and shows how they are used in PLINQ and the
Task Parallel Library.

For Further Reading Provides links to additional documentation and sample


resources for parallel programming in the .NET Framework.

See Also
Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4
Samples for Parallel Programming with the .NET Framework
Security in the .NET Framework
7/29/2017 • 1 min to read • Edit Online

The common language runtime and the .NET Framework provide many useful classes and services that enable
developers to easily write secure code and enable system administrators to customize the permissions granted to
code so that it can access protected resources. In addition, the runtime and the .NET Framework provide useful
classes and services that facilitate the use of cryptography and role-based security.

In This Section
Security Changes
Describes important changes to the .NET Framework security system.
Key Security Concepts
Provides an overview of common language runtime security features. This section is of interest to developers and
system administrators.
Role-Based Security
Describes how to interact with role-based security in your code. This section is of interest to developers.
Cryptography Model
Provides an overview of cryptographic services provided by the .NET Framework. This section is of interest to
developers.
Secure Coding Guidelines
Describes some of the best practices for creating reliable .NET Framework applications. This section is of interest to
developers.
Secure Coding Guidelines for Unmanaged Code
Describes some of the best practices and security concerns when calling unmanaged code.
Windows Identity Foundation
Describes how you can implement claims-based identity in your applications.

Related Sections
Development Guide
Provides a guide to all key technology areas and tasks for application development, including creating, configuring,
debugging, securing, and deploying your application, and information about dynamic programming,
interoperability, extensibility, memory management, and threading.
Serialization in .NET
8/4/2017 • 1 min to read • Edit Online

Serialization is the process of converting the state of an object into a form that can be persisted or transported. The
complement of serialization is deserialization, which converts a stream into an object. Together, these processes
allow data to be easily stored and transferred.
.NET features two serialization technologies:
Binary serialization preserves type fidelity, which is useful for preserving the state of an object between
different invocations of an application. For example, you can share an object between different applications
by serializing it to the Clipboard. You can serialize an object to a stream, to a disk, to memory, over the
network, and so forth. Remoting uses serialization to pass objects "by value" from one computer or
application domain to another.
XML serialization serializes only public properties and fields and does not preserve type fidelity. This is
useful when you want to provide or consume data without restricting the application that uses the data.
Because XML is an open standard, it is an attractive choice for sharing data across the Web. SOAP is likewise
an open standard, which makes it an attractive choice.

In This Section
Serialization How-to Topics
Lists links to How-to topics contained in this section.
Binary Serialization
Describes the binary serialization mechanism that is included with the common language runtime.
XML and SOAP Serialization
Describes the XML and SOAP serialization mechanism that is included with the common language runtime.
Serialization Tools
These tools help develop serialization code.
Serialization Samples
The samples demonstrate how to do serialization.

Reference
System.Runtime.Serialization Contains classes that can be used for serializing and deserializing objects.
System.Xml.Serialization
Contains classes that can be used to serialize objects into XML format documents or streams.
Developing for Multiple Platforms with the .NET
Framework
7/29/2017 • 2 min to read • Edit Online

You can develop apps for both Microsoft and non-Microsoft platforms by using the .NET Framework and Visual
Studio.

Options for cross-platform development


To develop for multiple platforms, you can share source code or binaries, and you can make calls between .NET
Framework code and Windows Runtime APIs.

IF YOU WANT TO... USE...

Share source code between Windows Phone 8.1 and Windows Shared projects (Universal Apps template in Visual Studio
8.1 apps 2013, Update 2).

- Currently no Visual Basic support.


- You can separate platform-specific code by using # if
statements.

For details, see:

- Build apps that target Windows and Windows Phone by


using Visual Studio (MSDN article)
- Using Visual Studio to build Universal XAML Apps (blog
post)
- Using Visual Studio to Build XAML Converged Apps (video)

Share binaries between apps that target different platforms Portable Class Library projects for code that is platform-
agnostic.

- This approach is typically used for code that implements


business logic.
- You can use Visual Basic or C#.
- API support varies by platform.
- Portable Class Library projects that target Windows 8.1 and
Windows Phone 8.1 support Windows Runtime APIs and
XAML. These features aren't available in older versions of the
Portable Class Library.
- If needed, you can abstract out platform-specific code by
using interfaces or abstract classes.

For details, see:

- Portable Class Library (MSDN article)


- How to Make Portable Class Libraries Work for You (blog
post)
- Using Portable Class Library with MVVM (MSDN article)
- App Resources for Libraries That Target Multiple Platforms
(MSDN article)
- .NET Portability Analyzer (Visual Studio extension)
IF YOU WANT TO... USE...

Share source code between apps for platforms other than Add as link feature.
Windows 8.1 and Windows Phone 8.1
- This approach is suitable for app logic that's common to
both apps but not portable, for some reason. You can use this
feature for C# or Visual Basic code.
For example, Windows Phone 8 and Windows 8 share
Windows Runtime APIs, but Portable Class Libraries do not
support Windows Runtime for those platforms. You can use
Add as link to share common Windows Runtime code
between a Windows Phone 8 app and a Windows Store app
that targets Windows 8.

For details, see:

- Share code with Add as Link (MSDN article)


- How to: Add Existing Items to a Project (MSDN article)

Write Windows Store apps using the .NET Framework or call Windows Runtime APIs from your .NET Framework C# or
Windows Runtime APIs from .NET Framework code Visual Basic code, and use the .NET Framework to create
Windows Store apps. You should be aware of API differences
between the two platforms. However, there are classes to help
you work with those differences.

For details, see:

- .NET Framework Support for Windows Store Apps and


Windows Runtime (MSDN article)
- Passing a URI to the Windows Runtime (MSDN article)
- System.IO.WindowsRuntimeStreamExtensions (MSDN API
reference page)
- System.WindowsRuntimeSystemExtensions (MSDN API
reference page)

Build .NET Framework apps for non-Microsoft platforms Portable Class Library reference assemblies in the .NET
Framework, and a Visual Studio extension or third-party tool
such as Xamarin.

For details, see:

- Portable Class Library now available on all platforms. (blog


post)
- Xamarin (Xamarin website)

Use JavaScript and HTML for cross-platform development Universal App templates in Visual Studio 2013, Update 2 to
develop against Windows Runtime APIs for Windows 8.1 and
Windows Phone 8.1. Currently, you can’t use JavaScript and
HTML with .NET Framework APIs to develop cross-platform
apps.

For details, see:

- JavaScript Project Templates


- Porting a Windows Runtime app using JavaScript to
Windows Phone
.NET Core Guide
8/9/2017 • 8 min to read • Edit Online

Check out the "Getting Started" tutorials to learn how to create a simple .NET Core application. It only takes a
few minutes to get your first app up and running.

.NET Core is a general purpose development platform maintained by Microsoft and the .NET community on
GitHub. It is cross-platform, supporting Windows, macOS and Linux, and can be used in device, cloud, and
embedded/IoT scenarios.
The following characteristics best define .NET Core:
Flexible deployment: Can be included in your app or installed side-by-side user- or machine-wide.
Cross-platform: Runs on Windows, macOS and Linux; can be ported to other operating systems. The
supported Operating Systems (OS), CPUs and application scenarios will grow over time, provided by
Microsoft, other companies, and individuals.
Command-line tools: All product scenarios can be exercised at the command-line.
Compatible: .NET Core is compatible with .NET Framework, Xamarin and Mono, via the .NET Standard.
Open source: The .NET Core platform is open source, using MIT and Apache 2 licenses. Documentation is
licensed under CC-BY. .NET Core is a .NET Foundation project.
Supported by Microsoft: .NET Core is supported by Microsoft, per .NET Core Support

Composition
.NET Core is composed of the following parts:
A .NET runtime, which provides a type system, assembly loading, a garbage collector, native interop and other
basic services.
A set of framework libraries, which provide primitive data types, app composition types and fundamental
utilities.
A set of SDK tools and language compilers that enable the base developer experience, available in the .NET
Core SDK.
The 'dotnet' app host, which is used to launch .NET Core apps. It selects the runtime and hosts the runtime,
provides an assembly loading policy and launches the app. The same host is also used to launch SDK tools in
much the same way.
Languages
The C# and F# languages (Visual Basic is coming) can be used to write applications and libraries for .NET Core.
The compilers run on .NET Core, enabling you to develop for .NET Core anywhere it runs. In general, you will not
use the compilers directly, but indirectly using the SDK tools.
The C# and F# compilers and the .NET Core tools are or can be integrated into several text editors and IDEs,
including Visual Studio, Visual Studio Code, Sublime Text and Vim, making .NET Core development an option in
your favorite coding environment and OS. This integration is provided, in part, by the good folks of the
OmniSharp project.
.NET APIs and Compatibility
.NET Core can be thought of as a cross-platform version of the .NET Framework, at the layer of the .NET
Framework Base Class Libraries (BCL). It implements the .NET Standard specification. .NET Core provides a subset
of the APIs that are available in the .NET Framework or Mono/Xamarin. In some cases, types are not fully
implemented (some members are not available or have been moved).
Look at the .NET Core roadmap to learn more about the .NET Core API roadmap.
Relationship to .NET Standard
The .NET Standard is an API spec that describes the consistent set of .NET APIs that developers can expect in each
.NET implementation. .NET implementations need to implement this spec in order to be considered .NET
Standard-compliant and to support libraries that target .NET Standard.
.NET Core implements .NET Standard, and therefore supports .NET Standard libraries.
Workloads
By itself, .NET Core includes a single application model -- console apps -- which is useful for tools, local services
and text-based games. Additional application models have been built on top of .NET Core to extend its
functionality, such as:
ASP.NET Core
Windows 10 Universal Windows Platform (UWP)
Xamarin.Forms when targeting UWP
Open Source
.NET Core is open source (MIT license) and was contributed to the .NET Foundation by Microsoft in 2014. It is now
one of the most active .NET Foundation projects. It can be freely adopted by individuals and companies, including
for personal, academic or commercial purposes. Multiple companies use .NET Core as part of apps, tools, new
platforms and hosting services. Some of these companies make significant contributions to .NET Core on GitHub
and provide guidance on the product direction as part of the .NET Foundation Technical Steering Group.

Acquisition
.NET Core is distributed in two main ways, as packages on NuGet.org and as standalone distributions.
Distributions
You can download .NET Core at the .NET Core Getting Started page.
The Microsoft .NET Core distribution includes the CoreCLR runtime, associated libraries, a console application
host and the dotnet app launcher. It is described by the Microsoft.NETCore.App metapackage.
The Microsoft .NET Core SDK distribution includes .NET Core and a set of tools for restoring NuGet packages
and compiling and building apps.
Typically, you will first install the .NET Core SDK to get started with .NET Core development. You may choose to
install additional .NET Core (perhaps pre-release) builds.
Packages
.NET Core Packages contain the .NET Core runtime and libraries (reference assemblies and implementations).
For example, System.Net.Http.
.NET Core Metapackages describe various layers and app-models by referencing the appropriate set of
versioned library packages.

Architecture
.NET Core is a cross-platform .NET implementation. The primary architectural concerns unique to .NET Core are
related to providing platform-specific implementations for supported platforms.
Environments
.NET Core is supported by Microsoft on Windows, macOS and Linux. On Linux, Microsoft primarily supports .NET
Core running on Red Hat Enterprise Linux (RHEL) and Debian distribution families.
.NET Core currently supports X64 CPUs. On Windows, X86 is also supported. ARM64 and ARM32 are in progress.
The .NET Core Roadmap provides more detailed information on workload and OS and CPU environment support
and plans.
Other companies or groups may support .NET Core for other app types and environment.
Designed for Adaptability
.NET Core has been built as a very similar but unique product relative to other .NET products. It has been
designed to enable broad adaptability to new platforms, for new workloads and with new compiler toolchains. It
has several OS and CPU ports in progress and may be ported to many more. An example is the LLILC project,
which is an early prototype of native compilation for .NET Core via the LLVM compiler.
The product is broken into several pieces, enabling the various parts to be adapted to new platforms on different
schedules. The runtime and platform-specific foundational libraries must be ported as a unit. Platform-agnostic
libraries should work as-is on all platforms, by construction. There is a project bias to reducing platform-specific
implementations to increase developer efficiency, preferring platform-neutral C# code whenever an algorithm or
API can be implemented in-full or in-part that way.
People commonly ask how .NET Core is implemented in order to support multiple operating systems. They
typically ask if there are separate implementations or if conditional compilation is used. It's both, with a strong
bias towards conditional compilation.
You can see in the chart below that the vast majority of CoreFX is platform-neutral code that is shared across all
platforms. Platform-neutral code can be implemented as a single portable assembly that is used on all platforms.

Windows and Unix implementations are similar in size. Windows has a larger implementation since CoreFX
implements some Windows-only features, such as Microsoft.Win32.Registry but does not yet implement any
Unix-only concepts. You will also see that the majority of the Linux and macOS implementations are shared
across a Unix implementation, while the Linux- and macOS-specific implementations are roughly similar in size.
There are a mix of platform-specific and platform-neutral libraries in .NET Core. You can see the pattern in a few
examples:
CoreCLR is platform-specific. It's built in C/C++, so is platform-specific by construction.
System.IO and System.Security.Cryptography.Algorithms are platform-specific, given that the storage and
cryptography APIs differ significantly on each OS.
System.Collections and System.Linq are platform-neutral, given that they create and operate over data
structures.

Comparisons to other .NET implementations


It is perhaps easiest to understand the size and shape of .NET Core by comparing it to existing .NET
implementations.
Comparison with .NET Framework
.NET was first announced by Microsoft in 2000 and then evolved from there. The .NET Framework has been the
primary .NET implementation produced by Microsoft during that 15+ year span.
The major differences between .NET Core and the .NET Framework:
App-models -- .NET Core does not support all the .NET Framework app-models, in part because many of
them are built on Windows technologies, such as WPF (built on top of DirectX). The console and ASP.NET Core
app-models are supported by both .NET Core and .NET Framework.
APIs -- .NET Core contains many of the same, but fewer, APIs as the .NET Framework, and with a different
factoring (assembly names are different; type shape differs in key cases). These differences currently typically
require changes to port source to .NET Core. .NET Core implements the .NET Standard API, which will grow to
include more of the .NET Framework BCL API over time.
Subsystems -- .NET Core implements a subset of the subsystems in the .NET Framework, with the goal of a
simpler implementation and programming model. For example, Code Access Security (CAS) is not supported,
while reflection is supported.
Platforms -- The .NET Framework supports Windows and Windows Server while .NET Core also supports
macOS and Linux.
Open Source -- .NET Core is open source, while a read-only subset of the .NET Framework is open source.
While .NET Core is unique and has significant differences to the .NET Framework and other .NET implementations,
it is straightforward to share code, using either source or binary sharing techniques.
Comparison with Mono
Mono is the original cross-platform and open source .NET implementation, first shipping in 2004. It can be
thought of as a community