effective c# 50 specific ways to improve your c# item 46~47 2012/09/25 1
TRANSCRIPT
Effective C# 50 Specific Ways to Improve Your C#
Item 46~47
Effective C# 50 Specific Ways to Improve Your C#
Item 46~47
2012/09/252012/09/25
1
AgendaAgenda
• Item 46: Minimize InteropItem 46: Minimize Interop
• Item 47: Prefer Safe CodeItem 47: Prefer Safe Code
MINIMIZE INTEROPMINIMIZE INTEROPItem 46:Item 46:
The cost of Data TransferThe cost of Data Transfer
• The cost and inefficiencies inherent in crossing the The cost and inefficiencies inherent in crossing the boundary between managed and unmanaged codeboundary between managed and unmanaged code– The first toll is paid by marshalling data back and forth between The first toll is paid by marshalling data back and forth between
the managed heap and the native heapthe managed heap and the native heap
– The second toll is the thunking cost of moving between The second toll is the thunking cost of moving between managed code and unmanaged codemanaged code and unmanaged code
– The third toll is yours alone: the amount of work you need to The third toll is yours alone: the amount of work you need to perform to manage this mixed environment. perform to manage this mixed environment. The third toll is the The third toll is the biggestbiggest
The cost of Data TransferThe cost of Data Transfer
• The cost and inefficiencies inherent in crossing the The cost and inefficiencies inherent in crossing the boundary between managed and unmanaged codeboundary between managed and unmanaged code– The first toll is paid by marshalling data back and forth between The first toll is paid by marshalling data back and forth between
the managed heap and the native heapthe managed heap and the native heap
– The second toll is the thunking cost of moving between The second toll is the thunking cost of moving between managed code and unmanaged codemanaged code and unmanaged code
– The third toll is yours alone: the amount of work you need to The third toll is yours alone: the amount of work you need to perform to manage this mixed environment. perform to manage this mixed environment. The third toll is the The third toll is the biggestbiggest
Our design decisions should minimize the third cost.Our design decisions should minimize the third cost.
The cost of Data TransferThe cost of Data Transfer
• Try to limit the data types passed between the managed Try to limit the data types passed between the managed and unmanaged layers of your code to blittable typesand unmanaged layers of your code to blittable types
– Blittable typeBlittable type
blittable typeblittable type
• A blittable type is one in which the managed and A blittable type is one in which the managed and unmanaged representations of the type are the sameunmanaged representations of the type are the same
• The benefitThe benefit– The contents can be copied without regard to the internal The contents can be copied without regard to the internal
structure of the objectstructure of the object
System.ByteSystem.Byte System.SbyteSystem.Sbyte System.Int16System.Int16System.UInt16System.UInt16 System.Int32System.Int32 System.UInt32System.UInt32System.Int64System.Int64 System.UInt64System.UInt64 System.UIntPtrSystem.UIntPtr
The blittable types are listed here:The blittable types are listed here:
The cost of Data TransferThe cost of Data Transfer
• If you can't restrict your data types to the blittable If you can't restrict your data types to the blittable typestypes
– Use Use InAttributeInAttribute and and OutAttributeOutAttribute to control when copies to control when copies are madeare made
– Make sure you apply the most restrictive In/Out Make sure you apply the most restrictive In/Out combination to avoid more copying than necessarycombination to avoid more copying than necessary
The cost of Data TransferThe cost of Data Transfer
• Increase performance by declaring how data should be Increase performance by declaring how data should be marshaledmarshaled– This is most common with stringsThis is most common with strings– Marshalling strings uses Marshalling strings uses BSTRsBSTRs by default. by default.
That's a safe strategyThat's a safe strategy It is It is the least efficientthe least efficient
For example:For example:The following declaration marshals the string as a LPWStr, or wchar*:The following declaration marshals the string as a LPWStr, or wchar*:
public void SetMsgpublic void SetMsg(( [ MarshalAs( [ MarshalAs( UnmanagedType.LPWStrUnmanagedType.LPWStr ) ] string msg ) ] string msg ););
Transfer program controlTransfer program control
• How you can transfer program control between How you can transfer program control between managed and unmanaged componentsmanaged and unmanaged components
– COM interopCOM interop
– Platform Invoke (P/Invoke)Platform Invoke (P/Invoke)
– Managed C++Managed C++
COM interopCOM interop
• BenefitBenefit– COM interop is COM interop is the easiest way the easiest way to leverage those COM to leverage those COM
components you are already usingcomponents you are already using
• DisadvantageDisadvantage– COM interop is COM interop is the least efficient way the least efficient way to access native code to access native code
in .NETin .NET
Platform Invoke (P/Invoke)Platform Invoke (P/Invoke)
• BenefitBenefit– This is This is the most efficient way the most efficient way to call any of the Win32 APIs to call any of the Win32 APIs
because you avoid the overhead associated with COMbecause you avoid the overhead associated with COM
• DisadvantageDisadvantage– You need to You need to hand-code the interface hand-code the interface to each method that you to each method that you
call using P/Invokecall using P/Invoke
– The more methods you invoke, the more method declarations The more methods you invoke, the more method declarations you must hand-codeyou must hand-code
Managed C++Managed C++
• You must build a You must build a managed C++ library managed C++ library on top of your on top of your legacy code to provide the bridge between the legacy code to provide the bridge between the unmanaged and managed types, unmanaged and managed types, providing the providing the marshalling support between the managed and marshalling support between the managed and unmanaged heapsunmanaged heaps
SummarySummary
• If you have existing COM objects written in any If you have existing COM objects written in any language, use COM interop. If you have existing C++ language, use COM interop. If you have existing C++ code, the /CLR switch and managed C++ provide the code, the /CLR switch and managed C++ provide the best strategy to access your existing native codebase best strategy to access your existing native codebase from new development created in C#. from new development created in C#. Pick the strategy Pick the strategy that takes the least timethat takes the least time
PREFER SAFE CODEPREFER SAFE CODEItem 37:Item 37:
Prefer Safe CodePrefer Safe Code
• Avoid accessing unmanaged memory whenever Avoid accessing unmanaged memory whenever possiblepossible
• Most common security concern is the file systemMost common security concern is the file system
Avoid accessing unmanaged memory whenever possibleAvoid accessing unmanaged memory whenever possible
• A safe assembly is one that does not use any pointers A safe assembly is one that does not use any pointers to access either the managed or unmanaged heapsto access either the managed or unmanaged heaps
• Almost all the C# code that you create is safeAlmost all the C# code that you create is safe
• Unless you turn on the /unsafe C# compiler option, Unless you turn on the /unsafe C# compiler option, you've created verifiably safe codeyou've created verifiably safe code
Avoid accessing unmanaged memory whenever possibleAvoid accessing unmanaged memory whenever possible
• When you use unsafe constructs, understand that When you use unsafe constructs, understand that unsafe code anywhere in an assembly affects the entire unsafe code anywhere in an assembly affects the entire assemblyassembly
• When you create unsafe code blocks, consider When you create unsafe code blocks, consider isolating isolating those algorithmsthose algorithms in their own assembly in their own assembly– This limits the affect that unsafe code has on your entire This limits the affect that unsafe code has on your entire
application application – If it's isolated, only callers who need the particular feature are If it's isolated, only callers who need the particular feature are
affectedaffected
File system security concern File system security concern
• Partially trusted assemblies can access their own Partially trusted assemblies can access their own specific isolated storage area, specific isolated storage area, but nowhere else on the but nowhere else on the file systemfile system
• You use isolated storage through the classes in the You use isolated storage through the classes in the System.IO.IsolatedStorageSystem.IO.IsolatedStorage namespace namespace
• The IsolatedStorageFile class contains methods very The IsolatedStorageFile class contains methods very similar to the System.IO.File classsimilar to the System.IO.File class
IsolatedStorageFileIsolatedStorageFile
IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForDomain( ); IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForDomain( ); IsolatedStorageFileStream myStream = new IsolatedStorageFileStream myStream = new IsolatedStorageFileStream( "SavedStuff.txt", FileMode.Create, iso ); IsolatedStorageFileStream( "SavedStuff.txt", FileMode.Create, iso ); StreamWriter wr = new StreamWriter( myStream ); StreamWriter wr = new StreamWriter( myStream ); wr.Close(); wr.Close();
Reading is equally familiar to anyone who has used file I/OReading is equally familiar to anyone who has used file I/O
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForDomain( ); IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForDomain( ); string[] files = isoStore.GetFileNames( "SavedStuff.txt" );string[] files = isoStore.GetFileNames( "SavedStuff.txt" ); if ( files.Length > 0 ) { StreamReader reader = new StreamReader( new if ( files.Length > 0 ) { StreamReader reader = new StreamReader( new IsolatedStorageFileStream( "SavedStuff.txt", FileMode.Open,isoStore ) );IsolatedStorageFileStream( "SavedStuff.txt", FileMode.Open,isoStore ) );reader.Close(); } reader.Close(); }
IsolatedStorageFileIsolatedStorageFile
• The .NET environment The .NET environment defines limits on the size of defines limits on the size of isolated storage for each applicationisolated storage for each application. This prevents . This prevents malicious code from consuming excessive disk space, malicious code from consuming excessive disk space, rendering a system unusablerendering a system unusable
• Isolated storage is hidden from other programs and Isolated storage is hidden from other programs and other usersother users
• Even though it is hidden, however, isolated storage is Even though it is hidden, however, isolated storage is not protected from not protected from unmanaged code unmanaged code or or from trusted from trusted usersusers. Do not use isolated storage for high-value . Do not use isolated storage for high-value secrets unless you apply additional encryptionsecrets unless you apply additional encryption
SummarySummary
• Avoid accessing unmanaged memory whenever Avoid accessing unmanaged memory whenever possiblepossible
• Use isolated storage whenever possibleUse isolated storage whenever possible