Advanced C# Eric Gunnerson Program Manager Visual C#.NET Microsoft Corporation.

Post on 02-Jan-2016

225 views 0 download

Tags:

Transcript of Advanced C# Eric Gunnerson Program Manager Visual C#.NET Microsoft Corporation.

Advanced C#Advanced C#Eric GunnersonEric Gunnerson

Program ManagerProgram ManagerVisual C# .NETVisual C# .NET

Microsoft CorporationMicrosoft Corporation

Advanced C# TopicsAdvanced C# Topics Visual Studio “Everett” FeaturesVisual Studio “Everett” Features Designing a New TypeDesigning a New Type Object DestructionObject Destruction Exception HandlingException Handling Unsafe CodeUnsafe Code

Visual Studio “Everett” FeaturesVisual Studio “Everett” Features Designing a New TypeDesigning a New Type Object DestructionObject Destruction Exception HandlingException Handling Unsafe CodeUnsafe Code

Advanced C# TopicsAdvanced C# Topics

Everett DemoEverett Demo

Designing a New TypeDesigning a New Type

C# has both C# has both reference and reference and value typesvalue types

Which is the right Which is the right one to use?one to use?

What are they?What are they?

Reference types:Reference types: Heap allocatedHeap allocated Tracked by the GCTracked by the GC Support inheritance, polymorphism, etc.Support inheritance, polymorphism, etc.

Value types:Value types: Stack or inline allocatedStack or inline allocated Not tracked by the GCNot tracked by the GC No inheritance, limited polymorphismNo inheritance, limited polymorphism

Other LanguagesOther Languages

Smalltalk only supports reference typesSmalltalk only supports reference types Simple, consistent modelSimple, consistent model DisadvantagesDisadvantages

““int j = 5;” does a heap allocationint j = 5;” does a heap allocation 100 ints in an array is 100 allocations100 ints in an array is 100 allocations Doesn’t interop well with existing primitive typesDoesn’t interop well with existing primitive types

Value TypesValue Types Advantages:Advantages:

Allocation is very fastAllocation is very fast Arrays involve a single allocationArrays involve a single allocation Reduced memory pressureReduced memory pressure

Less work for the GCLess work for the GC

Disadvantages:Disadvantages: No inheritanceNo inheritance Only polymorphic when boxedOnly polymorphic when boxed Boxing involves overheadBoxing involves overhead

Reference TypesReference Types

The basic type in .netThe basic type in .net Advantages:Advantages:

All object-oriented goodiesAll object-oriented goodies polymorphism, etc.polymorphism, etc.

Good performanceGood performance

Disadvantages:Disadvantages: Always requires heap allocationAlways requires heap allocation

GuidelinesGuidelines Use value types for:Use value types for:

Building a new data type (ie Complex)Building a new data type (ie Complex) LotsLots of small objects of small objects

Only really useful if they’re in an arrayOnly really useful if they’re in an array If not, boxing often means this isn’t worth itIf not, boxing often means this isn’t worth it

Size of typeSize of type Framework guidelines say <= 16 bytesFramework guidelines say <= 16 bytes Depends on usage of the typeDepends on usage of the type Benchmark to validate for your appBenchmark to validate for your app

If you hit limitations, you’re using it If you hit limitations, you’re using it wrongwrong

Visual Studio “Everett” FeaturesVisual Studio “Everett” Features Designing a New TypeDesigning a New Type Object DestructionObject Destruction Exception HandlingException Handling Ref and foreachRef and foreach Unsafe CodeUnsafe Code

Advanced C# TopicsAdvanced C# Topics

Object Object DestructionDestruction

Goal: Be able to control exactly Goal: Be able to control exactly when objects are destroyedwhen objects are destroyed

You want itYou want it You can’t have itYou can’t have it

A very complicated discussionA very complicated discussion See See http://www.gotdotnet.com/team/csharp/informationhttp://www.gotdotnet.com/team/csharp/information

Look for article on Resource managementLook for article on Resource management

Object DestructionObject Destruction

Garbage collection means you aren’t in Garbage collection means you aren’t in controlcontrol

GC chooses:GC chooses: When objects are destroyedWhen objects are destroyed Order of destructionOrder of destruction

Garbage collector can’t clean up Garbage collector can’t clean up unmanaged objectsunmanaged objects

How Bad is It?How Bad is It?

Mostly an issue for wrapper objectsMostly an issue for wrapper objects Database handlesDatabase handles FilesFiles GDI objects (fonts, pens, etc.)GDI objects (fonts, pens, etc.) Any object the GC doesn’t trackAny object the GC doesn’t track

All objects get cleaned upAll objects get cleaned up Some may take a bit longerSome may take a bit longer

Wrapper objectsWrapper objects

Cleanup at GC timeCleanup at GC time Objects with unmanaged resources Objects with unmanaged resources

implement a finalizer to free those implement a finalizer to free those resourcesresources

Early CleanupEarly Cleanup Objects implement IDisposable, users call Objects implement IDisposable, users call

Dispose() to clean upDispose() to clean up

Scenario 1Scenario 1User Calls Dispose()User Calls Dispose()

Unmanaged Resource

Font object

Dispose()

Dispose()

freeIntPtr myResource;

Font font;

Dispose() means free my resources, and call Dispose() on any contained objects

Scenario 2Scenario 2Object Finalized by GCObject Finalized by GC

Unmanaged Resource

Font object

Finalize()

Dispose()?

freeIntPtr myResource;

Font font;

Finalize() means free my resources only; other managed resources will also get finalized

X

Finalize()

Implementing Implementing IDisposableIDisposable

Design pattern for early cleanupDesign pattern for early cleanup Only required when you:Only required when you:

Wrap unmanaged resourcesWrap unmanaged resources You’ll need a destructor tooYou’ll need a destructor too

oror Need to be able to clean up earlyNeed to be able to clean up early

DestructorsDestructors

Object.Finalize is not accessible in Object.Finalize is not accessible in C#C#public class Resource: IDisposablepublic class Resource: IDisposable

{{ ~Resource() {...}~Resource() {...}}}

public class Resource: IDisposablepublic class Resource: IDisposable{{ protected override void Finalize() {protected override void Finalize() { try {try { ...... }} finally {finally { base.Finalize();base.Finalize(); }} }}}}

Doing the Doing the ImplementationImplementation

public class Resource: IDisposablepublic class Resource: IDisposable{{ IntPtr myResource;IntPtr myResource; Font font;Font font;

protected virtual void Dispose(bool disposing) {protected virtual void Dispose(bool disposing) { if (disposing) {if (disposing) { font.Dispose();font.Dispose(); GC.SuppressFinalize(this);GC.SuppressFinalize(this); }} FreeThatResource(myResource);FreeThatResource(myResource); }} public void Dispose() {public void Dispose() { Dispose(true);Dispose(true); }} ~Resource() {~Resource() { Dispose(false);Dispose(false); }}}}

Visual Studio “Everett” FeaturesVisual Studio “Everett” Features Designing a New TypeDesigning a New Type Object DestructionObject Destruction Exception HandlingException Handling Unsafe CodeUnsafe Code

Advanced C# TopicsAdvanced C# Topics

Exception HandlingException Handling

Provides tremendous benefitsProvides tremendous benefits

Requires a different way of thinkingRequires a different way of thinking

The old wayThe old way

RETVAL Process(int a, int x, int y, int z)RETVAL Process(int a, int x, int y, int z){{RETVAL retval;RETVAL retval;if ((retval = function(x, y, z)) != OK)if ((retval = function(x, y, z)) != OK)

return retval;return retval;

if ((retval = function2(a, y)) != OK)if ((retval = function2(a, y)) != OK)return retval;return retval;

}}

Option 1Option 1void Process(int a, int x, int y, int z)void Process(int a, int x, int y, int z){{ trytry {{

function(x, y, z);function(x, y, z);}}catch (Exception e)catch (Exception e){{

throw e;throw e;}}

trytry {{

function2(a, y);function2(a, y);}}catch (Exception e)catch (Exception e){{

throw e;throw e;}}

}}

Option 2Option 2

void Process(int a, int x, int y, int z)void Process(int a, int x, int y, int z){{ trytry {{

function(x, y, z);function(x, y, z);function2(a, y);function2(a, y);

}}catch (Exception e)catch (Exception e){{

throw e;throw e;}}

}}

Option 3Option 3void Process(int a, int x, int y, int z)void Process(int a, int x, int y, int z){{

function(x, y, z);function(x, y, z);function2(a, y);function2(a, y);

}}

Exception HandlingException Handling

You get correct behavior by defaultYou get correct behavior by default Only catch an exception when you can Only catch an exception when you can

do something useful for the userdo something useful for the user You can write lots of unnecessary code, You can write lots of unnecessary code,

but at least your code will be less robustbut at least your code will be less robust

When to catchWhen to catch

Something specific happens, and we can Something specific happens, and we can helphelp

trytry{{ StreamReader s = File.OpenText(filename);StreamReader s = File.OpenText(filename);}}

catch (Exception e)catch (Exception e){{ Console.WriteLine(“Invalid filename: {0}”, filename);Console.WriteLine(“Invalid filename: {0}”, filename);}}

trytry{{ StreamReader s = File.OpenText(filename);StreamReader s = File.OpenText(filename);}}

catch (FileNotFoundException e)catch (FileNotFoundException e){{ Console.WriteLine(e);Console.WriteLine(e);}}

trytry{{ ExecuteBigProcess();ExecuteBigProcess();}}

catch (Exception e)catch (Exception e){{ log.WriteLine(e.ToString());log.WriteLine(e.ToString()); throw;throw;}}

trytry{{ ExecuteBigProcess();ExecuteBigProcess();}}

catch (Exception e)catch (Exception e){{ throw new throw new MyException(“Error executing BigProcess”, e); MyException(“Error executing BigProcess”, e);}}

When to catchWhen to catch

We need to log or wrap an exceptionWe need to log or wrap an exception

When to catchWhen to catch

We’d die otherwiseWe’d die otherwisepublic static void Main()public static void Main(){{ while (true)while (true) {{ trytry {{ MainLoop();MainLoop(); }} catch (Exception e)catch (Exception e) {{ Console.WriteLine(“Exception caught, trying to continue”);Console.WriteLine(“Exception caught, trying to continue”); Console.WriteLine(e);Console.WriteLine(e); }} }}}}

Finally statementFinally statement

If an exception is thrown andIf an exception is thrown and There’s something to clean upThere’s something to clean up

Close a fileClose a file Release a DB handleRelease a DB handle

Using statement makes this easierUsing statement makes this easier Works on anything that implements Works on anything that implements

IDisposableIDisposable

Using StatementUsing Statement Acquire, Execute, Release patternAcquire, Execute, Release pattern Works with any IDisposable objectWorks with any IDisposable object

Data access classes, streams, text readers Data access classes, streams, text readers and writers, network classes, etc.and writers, network classes, etc.

using (Resource res = new Resource()) {using (Resource res = new Resource()) { res.DoWork();res.DoWork();}}

Resource res = new Resource(...);Resource res = new Resource(...);try {try { res.DoWork();res.DoWork();}}finally {finally { if (res != null) ((IDisposable)res).Dispose();if (res != null) ((IDisposable)res).Dispose();}}

Using StatementUsing Statement

static void Copy(string sourceName, string destName) {static void Copy(string sourceName, string destName) { Stream input = File.OpenRead(sourceName);Stream input = File.OpenRead(sourceName); Stream output = File.Create(destName);Stream output = File.Create(destName); byte[] b = new byte[65536];byte[] b = new byte[65536]; int n;int n; while ((n = input.Read(b, 0, b.Length)) != 0) {while ((n = input.Read(b, 0, b.Length)) != 0) { output.Write(b, 0, n);output.Write(b, 0, n); }} output.Close();output.Close(); input.Close();input.Close();}}

static void Copy(string sourceName, string destName) {static void Copy(string sourceName, string destName) { Stream input = File.OpenRead(sourceName);Stream input = File.OpenRead(sourceName); try {try { Stream output = File.Create(destName);Stream output = File.Create(destName); try {try { byte[] b = new byte[65536];byte[] b = new byte[65536]; int n;int n; while ((n = input.Read(b, 0, b.Length)) != 0) {while ((n = input.Read(b, 0, b.Length)) != 0) { output.Write(b, 0, n);output.Write(b, 0, n); }} }} finally {finally { output.Close();output.Close(); }} }} finally {finally { input.Close();input.Close(); }}}}

static void Copy(string sourceName, string destName) {static void Copy(string sourceName, string destName) { using (Stream input = File.OpenRead(sourceName))using (Stream input = File.OpenRead(sourceName)) using (Stream output = File.Create(destName)) {using (Stream output = File.Create(destName)) { byte[] b = new byte[65536];byte[] b = new byte[65536]; int n;int n; while ((n = input.Read(b, 0, b.Length)) != 0) {while ((n = input.Read(b, 0, b.Length)) != 0) { output.Write(b, 0, n);output.Write(b, 0, n); }} }}}}

Exceptions vs Return Exceptions vs Return CodesCodes

Exceptions are meant for Exceptions are meant for exceptional casesexceptional cases Invalid parametersInvalid parameters Can’t perform operationCan’t perform operation

Should not occur during normal Should not occur during normal program operationprogram operation User interaction is a grey areaUser interaction is a grey area

Using Return ValuesUsing Return Values

Okay if your caller Okay if your caller alwaysalways will have to will have to check and recover from somethingcheck and recover from something Make sure you don’t force them to write:Make sure you don’t force them to write:

Shouldn’t be possible to do the wrong Shouldn’t be possible to do the wrong thingthing File.Open() returns null on file not foundFile.Open() returns null on file not found You can’t ignore thisYou can’t ignore this

bool success = TryOperation(param1, param2);bool success = TryOperation(param1, param2);if (!success)if (!success) return success;return success;

SummarySummary

Understand how the model worksUnderstand how the model works Don’t work too hardDon’t work too hard If you can’t do something useful, If you can’t do something useful,

don’t catchdon’t catch

Visual Studio “Everett” FeaturesVisual Studio “Everett” Features Designing a New TypeDesigning a New Type Object DestructionObject Destruction Exception HandlingException Handling Unsafe CodeUnsafe Code

Advanced C# TopicsAdvanced C# Topics

Unsafe CodeUnsafe Code When pointers are a necessityWhen pointers are a necessity

Advanced COM and P/Invoke interopAdvanced COM and P/Invoke interop Existing binary structuresExisting binary structures Performance extremesPerformance extremes

Low-level code without leaving the boxLow-level code without leaving the box Basically “inline C”Basically “inline C”

struct COFFHeader {struct COFFHeader { public ushort MachineType;public ushort MachineType; public ushort NumberOfSections;public ushort NumberOfSections; … … public ushort Characteristics;public ushort Characteristics;}}

private COFFHeader fileHeader;private COFFHeader fileHeader;

void ReadHeader(BinaryStream InFile)void ReadHeader(BinaryStream InFile){{ fileHeader.MachineType = inFile.ReadUInt16();fileHeader.MachineType = inFile.ReadUInt16(); fileHeader.NumberOfSections = inFile.ReadUInt16();fileHeader.NumberOfSections = inFile.ReadUInt16(); // …// … fileHeader.Characteristics = inFile.ReadUInt16();fileHeader.Characteristics = inFile.ReadUInt16();}}

private COFFHeader fileHeader;private COFFHeader fileHeader;

unsafe void ReadHeader(BinaryStream InFile)unsafe void ReadHeader(BinaryStream InFile){{ byte[] buffer = InFile.ReadBytes(sizeof(COFFHeader));byte[] buffer = InFile.ReadBytes(sizeof(COFFHeader)); fixed (byte* headerPtr = buffer) fixed (byte* headerPtr = buffer) {{ fileHeader = *((COFFHeader*)headerPtr);fileHeader = *((COFFHeader*)headerPtr); }}}}

Existing Binary Existing Binary Structures Structures

Image ProcessingImage Processing

demodemo

Additional ResourcesAdditional Resources

C# Community SitesC# Community Sites http://www.csharp.nethttp://www.csharp.net

See information page for my columnsSee information page for my columns Sign up for C# Community NewsletterSign up for C# Community Newsletter

C# newsgroupC# newsgroup microsoft.public.dotnet.languages.csharmicrosoft.public.dotnet.languages.cshar

pp

Me: EricGu@Microsoft.comMe: EricGu@Microsoft.com

Thank YouThank You

Questions?Questions?