Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts
-
.NET 4.0 New Types
Now that the lowdown changes are out of the way, lets look at some of the new types in .NET 4.0 and modifications to existing classes and methods.
BigInteger
Working with really big numbers in .NET can get a bit strange. For example, try the following example (without advanced options such as overflow checking) and you might be surprised at the result you get:
<pre class="brush:csharp">
int a = 2000000000;
Console.WriteLine(a * 2);
Console.ReadKey();
</pre>
Surely the result is 4000000000? Running this code will give you the following answer:
-294967296
This issue occurs due to how this type of integer is represented in binary and the overflow that occurs. After the multiplication, the number gets bigger than this type can handle, so it actually becomes negative.
OK, so not many applications will need to hold values of this magnitude. But for those that do, .NET 4.0 introduces the BigInteger class (in the System.Numerics namespace) that can hold really big numbers.
BigInteger is an immutable type with a default value of 0 with no upper or lower bounds. This upper value is subject to available memory, of course, and if exceeded, an out-of-memory exception will be thrown. But seriously, what are you holding? Even the U.S. national debit isn’t that big.
BigIntegers can be initialized in two main ways:
<pre class="brush:csharp">
BigInteger bigIntFromDouble = new BigInteger(4564564564542332);
BigInteger assignedFromDouble = (BigInteger) 4564564564542332;
</pre>
BigInteger has a number of useful (and self-explanatory) methods not found in other numeric types:
• IsEven()
• IsOne()
• IsPowerOfTwo()
• IsZero()
• IsSign()
Lazy<T>
Lazy<T> allows you to easily add lazy initialization functionality to your variables. Lazy initialization saves allocating memory until the object is actually used. So if you never end up accessing your object, you have avoided using the resources to allocate it. Additionally, you have spread out resource allocation through your application’s life cycle, which is important for the responsiveness of UI-based applications. Lazy<T> couldn’t be easier to use:
<pre class="brush:csharp">
Lazy<BigExpensiveObject> instance;
</pre>
Lazy has implications for multithreaded scenarios. Some of the constructors for the Lazy type have an isThreadSafe parameter (see MSDN for more details of this: http://msdn.microsoft.com/en-us/library/dd997286%28VS.100%29.aspx).
Memory Mapping Files
A memory mapped file maps the contents of a file into memory, allowing you to work with it in a very efficient manner. Memory mapped files can also be used for interprocess communication, allowing you to share information between two applications:
Let’s see how to use memory mapped files inter process communication:
1. Create a new console application called Chapter4.MemoryMappedCreate.
2. Add the following using statements:
<pre class="brush:csharp">
using System.IO;
using System.IO.MemoryMappedFiles;
</pre>
3. Enter the following code in the Main() method:
<pre class="brush:csharp">
//Create a memory mapped file
using (MemoryMappedFile MemoryMappedFile = MemoryMappedFile.CreateNew("test", 100))
{
MemoryMappedViewStream stream = MemoryMappedFile.CreateViewStream();
using (BinaryWriter writer = new BinaryWriter(stream))
{
er.Write("hello memory mapped file!");
}
Console.WriteLine("Press any key to close mapped file");
Console.ReadKey();
}
</pre>
4. Add another Console application called Chapter4.MemoryMappedRead to the solution.
5. Add the following using statements:
<pre class="brush:csharp">
using System.IO;
using System.IO.MemoryMappedFiles;
</pre>
6. Enter the following code in the Main() method:
<pre class="brush:csharp">
//Read a memory mapped file
using (MemoryMappedFile MemoryMappedFile = MemoryMappedFile.OpenExisting("test"))
{
using (MemoryMappedViewStream Stream = MemoryMappedFile.CreateViewStream())
{
BinaryReader reader = new BinaryReader(Stream);
Console.WriteLine(reader.ReadString());
}
Console.ReadKey();
}
</pre>
7. You have to run both projects to demonstrate memory mapped files. First, right-click the project.MemoryMappedCreate and select Debug -> Start new instance. A new memory mapped file will be created and a string written to it.
8. Right-click the project Chapter4.MemoryMappedRead and select Debug -> Start new instance. You should see the string hello memory mapped file! read and printed from the other project.
The other main use of memory mapped files is for working with very large files. For an example, please refer to this MSDN article: http://msdn.microsoft.com/enus/library/system.io.memorymappedfiles.memorymappedfile(VS.100).aspx.
SortedSet<T>
Sorted set is a new type of collection in the System.Collections.Generic namespace that maintains the order of items as they are added. If a duplicate item is added to a sorted set, it will be ignored, and a value of false is returned from the SortedSet’s Add() method. The following example demonstrates creating a sorted list of integers with a couple of duplicates in:
<pre class="brush:csharp">
SortedSet<int> MySortedSet = new SortedSet<int> { 8, 2, 1, 5, 10, 5, 10, 8 };
</pre>
ISet<T> Interface
.NET 4.0 introduces ISet<T>, a new interface utilized by SortedSet and HashSet and surprisingly enough for implementing set classes.
Tuple
A tuple is a typed collection of fixed size. Tuples were introduced for interoperability with F# and IronPython, but can also make your code more concise.
Tuples are very easy to create:
<pre class="brush:csharp">
Tuple<int, int, int, int, int> MultiplesOfTwo = Tuple.Create(2, 4, 6, 8, 10);
</pre>
Individual items in the tuple can then be queried with the Item property:
<pre class="brush:csharp">
Console.WriteLine(MultiplesOfTwo.Item2);
</pre>
Tuples might contain up to seven elements; if you want to add more items, you have to pass in another tuple to the Rest parameter:
<pre class="brush:csharp">
var multiples = new Tuple<int, int, int, int, int, int, int,Tuple<int,int,int>>(2, 4, 6, 8,
10, 12, 14, new Tuple<int,int,int>(3,6,9));
</pre>
Items in the second tuple can be accessed by querying the Rest property:
<pre class="brush:csharp">
Console.WriteLine(multiples.Rest.Item1);
</pre>
System.Numerics.Complex
Mathematicians will be glad of the addition of the new Complex type: a structure for representing and manipulating complex numbers, meaning that they will no longer have to utilize open source libraries or projects. Complex represents both a real and imaginary number, and contains support for both rectangular and polar coordinates:
<pre class="brush:csharp">
Complex c1 = new Complex(8, 2);
Complex c2 = new Complex(8, 2);
Complex c3 = c1 + c2;
</pre>
And I am afraid my math skills aren’t up to saying much more about this type, so let’s move on.
System.IntPtr and System.UIntPtr
Addition and subtraction operators are now supported for System.IntPtr and System.UIntPtr. Add()() and Subtract() methods have also been added to these types.
Tail Recursion
The CLR contains support for tail recursion, although this is only currently accessible through F#.
Source of Information : Apress Introducing dot NET 4.0 with Visual Studio 2010
more
-
Exception Handling
Exception handling has been improved in .NET 4.0 with the introduction of the System.Runtime. ExceptionServices namespace, which contains classes for advanced exception handling.
CorruptedStateExceptions
Many developers (OK, I might have done this, too) have written code such as the following:
try
{
// do something that may fail
}
catch(System.exception e)
{
...
}
This is almost always a very naughty way to write code because all exceptions will be hidden. Hiding exceptions you don’t know about is rarely a good thing, and if you do know about them, you should inevitably be handling them in a better way. Additionally, there are some exceptions that should never be caught (even by lazy developers) such as lowdown beardy stuff such as access violations and calls to illegal instructions. These exceptions are potentially so dangerous that it’s best to just shut down the application as quick as possible before it can do any further damage.
So in .NET 4.0, corrupted state exceptions will never be caught even if you specify a try a catch block. However, if you do want to enable catching of corrupted state exceptions application-wide (e.g., to route them to an error-logging class), you can add the following setting in your applications configuration file:
LegacyCorruptedStateExceptionsPolicy=true
This behavior can also be enabled on individual methods with the following attribute:
[HandleProcessCorruptedStateExceptions]
Source of Information : Apress Introducing dot NET 4.0 with Visual Studio 2010
more
-
Starting Threads
Creating a thread is very simple. Take a look at the following example:
using System;
using System.Threading;
public class EntryPoint
{
private static void ThreadFunc()
{
Console.WriteLine("Hello from new thread {0}!",
Thread.CurrentThread.GetHashCode());
}
static void Main()
{
// Create the new thread.
Thread newThread =
new Thread(new ThreadStart(EntryPoint.ThreadFunc));
Console.WriteLine("Main Thread is {0}",
Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Starting new thread...");
// Start the new thread.
newThread.Start();
// Wait for new thread to finish.
newThread.Join();
Console.WriteLine("New thread has finished");
}
}
All you have to do is create a new System.Thread object and pass an instance of the ThreadStart delegate as the parameter to the constructor. The ThreadStart delegate references a method that takes no parameters and returns no parameters. In the previous example, I chose to use the static ThreadFunc method as the start of execution for the new thread. I could have just as easily chosen to use any other method visible to the code creating the thread, as long as it neither accepted nor returned parameters. Notice that the code also outputs the managed thread identifier in two different ways to demonstrate how you can identify threads in the managed world. In the unmanaged C++ world, you would use the thread ID obtained via the Win32 API. In the managed world of .NET 1.1, you instead use the value returned by GetHashCode. As long as this thread is alive, it is guaranteed never to collide with any other thread in any application domain of this process. The thread hash code is not globally unique on the entire system. Starting with .NET 2.0, you can get the managed thread id by accessing the
Thread.ManagedThreadId property. Also, you can see how you can get a reference to the current thread by accessing the static property Thread.CurrentThread. Finally, notice the call to the Join method on the newThread object. In native Win32 code, you normally wait for a thread to finish by waiting on its handle. When the thread finishes running, the operating system signals its handle and the wait completes. The Thread.Join method encapsulates this functionality. In this case, the code waits forever for the thread to finish. Thread.Join also provides a few overloads that allow you to specify a timeout period on the wait.
When you create a separate thread, it is subject to the rules of the thread scheduler on the system, just like any other thread. However, sometimes you need to create threads that carry a little more or a little less weight when the scheduler algorithm is deciding which thread to execute next. You can control the priority of a managed thread via the Thread.Priority property. You can adjust this value as necessary during execution of the thread. It’s actually a rare occurrence that you’ll need to adjust this value. All threads start out with the priority of Normal from the ThreadPriority enumeration.
There is some confusion in the MSDN documentation regarding whether one should call Thread.GetHashCode or access the Thread.ManagedThreadId property. If you read the MSDN documentation carefully, the summary page for System.Thread indicates that GetHashCode is what you should use to obtain the unique managed thread identifier during the duration the thread is alive. But if you look at the documentation for Thread.GetHashCode, it states that you should use the ManagedThreadId property instead. By debugging into the example application above using windbg in the Debugging Tools for Windows package in concert with the sos.dll debugger extension, I was able to determine that the results of GetHashCode and the ManagedThreadId property accessor both harvest the value from the same location within an internal structure of the Thread object instance. Arguably, ManagedThreadId makes the code easier to read because it’s more obvious what it is. Additionally, ManagedThreadId was introduced in .NET 2.0 and if you are targeting .NET 1.1, then you must use GetHashCode. I expect this confusion in the MSDN documentation to go away at some point soon, as it is a documentation bug. You should always rely upon ManagedThreadId even though GetHashCode returns the same value for the purposes of backwards compatibility. Throughout the rest of this chapter, I will be using ManagedThreadId rather than GetHashCode.
more
-
Overview of New C# 4.0 Features
Arguably, the theme of the new features of C# 4.0 centers on interoperability. The biggest feature in that respect is the new dynamic type. By using dynamic, the cumbersome rigmarole of interoperating with COM objects or types created by .NET dynamic languages is a thing of the past. Visual Basic has had a leg up on C# for quite some time with respect to interoperability. But with C# 4.0, the playing field has been leveled.
.
Each time the C# development team embarks on a new feature cycle, they must choose from a list of feature ideas and requests. For some time, default method argument values has been on that list, but prior to C# 4.0, has never been implemented. However, interoperability is just the compelling reason needed to reach the tipping point. With default argument values, interoperating with COM types becomes even easier. However, there is another feature that goes hand-in-hand with default arguments values and that is named arguments. In C# 4.0, you can pass arguments to methods as named arguments such that ordering of arguments in the argument list is irrelevant. As nice as that sounds, it is even more powerful when you couple it with default argument values and COM interoperability. Often, COM automation interfaces contain methods with many parameters that are often optional. Using default arguments, you do not have to provide values for all of them. And by using named arguments, you can pick and choose which of the arguments in the default list of arguments you want to provide.
Rounding out the new features of C# 4.0 is that of variance. New contextual keyword support was added to allow one to declare covariant and contravariant generic interfaces and delegates. By decorating the generic arguments with the in and out keywords, you can declare the interface as co- or contravariant. This allows such intuitive implicit covariant conversions from IEnumerable<string> references to IEnumerable<object> references. This is something that was not possible prior to C# 4.0. This type of covariance has always been supported for arrays, however, it is broken.
Source of Information : Apress Accelerated C Sharp 2010
more
-
Overview of Features Added in C# 3.0
C# 3.0 included some great new features. Most of the new features are stepping stones designed to support Language Integrated Query (LINQ). Nevertheless, all of them are extremely useful when used individually outside of the context of LINQ. Many of them allow programmers to employ functional programming techniques more easily.
C# now supports implicitly typed local variables by making use of a new keyword var. It’s important to note that these variables are not typeless; rather, their type is inferred at compile time.
Have you ever wanted to create a simple type to hold some related data but been annoyed at having to create an entire new class? In many cases, the support for anonymous types helps relieve you of this burden. Using anonymous types, you can define and instantiate a type all in one compound statement.
Auto-implemented properties are another helpful feature to save us some typing and reduce the potential to introduce bugs. How many times have you simply declared a class to hold a few pieces of data and been annoyed with the amount of typing required to create property accessors for that data? After all, doing so follows good encapsulation practices. Thankfully, auto-implemented properties greatly reduce the amount of typing necessary to define properties on types.
While we’re on the subject of conveniences, C# 3.0 also introduced two new features that help when instantiating and initializing object instances. Using object and collection initializers, you can instantiate and initialize either an object or a collection in one compound statement.
C# 2.0 introduced partial class definitions to facilitate using code generators. C# 3.0 adds to that by introducing partial methods. Using partial methods, a code generator can declare a method signature and the consumer of that generated code, the one that creates the rest of the partial class definition, can choose to implement it or not.
Extension methods are one of the most exciting new features. Taken from the surface view, they are merely static methods that can be called as if they were instance methods. They do not get any special access into the instance they are operating on, so in that respect, they are just like static methods. However, the syntax they foster allows us to program in a more functional manner, usually resulting in clearer and more readable code.
Probably more compelling than extension methods is support for lambda expressions. Lambda expressions supersede support for anonymous methods. That is, if lambda expressions had existed in C# 2.0, there would have been no need for anonymous methods at all. However, lambda expressions offer much more than anonymous methods as they can be converted into both delegates and expression trees.
The granddaddy of all new C# 3.0 features has to be LINQ, which builds upon all of the new features, especially extension methods, lambda expressions, and anonymous types. It also adds some new language keywords to allow us to code intuitive query statements, thus seamlessly bridging the gap between the object-oriented world and the data world. You can use LINQ to access data from multiple sources. Visual Studio provides the capability to use LINQ on native object collections, SQL data stores, and XML. Support for many other data sources is coming soon from both Microsoft and third parties.
For example, you’ll be able to use LINQ to connect to Windows Management Instrumentation (WMI), the Document Object Model (DOM), and the Web. Additionally, there are implementations in the works to use LINQ against popular web sites such as Google and Flickr.
Source of Information : Apress Accelerated C Sharp 2010
more
-
Overview of Features Added in C# 2.0
Since its initial release in late 2000, the C# language has evolved considerably. This evolution has likely been accelerated thanks to the wide adoption of C#. With the release of Visual Studio 2005 and the .NET Framework 2.0, the C# compiler supported the C# 2.0 enhancements to the language. This was great news, since C# 2.0 included some handy features that provided a more natural programming experience as well as greater efficiency.
Arguably, the meatiest addition to C# 2.0 was support for generics. The syntax is similar to C++ templates, but the main difference is that constructed types created from .NET generics are dynamic in nature—that is, they are bound and constructed at runtime. This differs from C++ concrete types created from templates, which are static in the sense that they are bound and created at compile time.5 Generics are most useful when used with container types such as vectors, lists, and hash tables, where they provide the greatest efficiency gains. Generics can treat the types that they contain specifically by their type, rather than by using the base type of all objects, System.Object.
C# 2.0 added support for anonymous methods. An anonymous method is sometimes referred to as a lambda function, which comes from functional programming disciplines. C# anonymous methods are extremely useful with delegates and events. Delegates and events are constructs used to register callback methods that are called when triggered. Normally, you wire them up to a defined method somewhere. But with anonymous methods, you can define the delegate’s or event’s code inline, at the point where the delegate or event is set up. This is handy if your delegate merely needs to perform some small amount of work for which an entire method definition would be overkill. What’s even better is that the anonymous method body has access to all variables that are in scope at the point it is defined.
Lambda expressions, which are new to C# 3.0, supersede anonymous methods and make for more readable code. C# 2.0 added support for iterator blocks. Anyone familiar with the C++ Standard Template Library (STL) knows about iterators and their usefulness. In C#, you typically use the foreach statement to iterate over an object that behaves as a collection. That collection object must implement the IEnumerable interface, which includes the GetEnumerator method. Implementing the GetEnumerator method on container types is typically very tedious. However, when using C# iterators, implementing the GetEnumerator method is a snap.
Finally, C# 2.0 added support for partial types. Prior to C# 2.0, you had to define each C# class entirely in one file (also called a compilation unit). This requirement was relaxed with the support for partial types. This was great news for those who rely upon code generators to provide skeleton code. For example, you can use the Visual Studio wizards to generate such useful things as System.Data.DataSet derived types for accessing data in a database. Prior to C# 2.0, it was problematic if you needed to make modifications to the generated code. You either had to derive from or contain the generated type in a new type while specializing its implementation or you had to edit the generated code. Editing the generated code was risky because you normally lost those changes when the wizard was forced to regenerate the type for some reason. Partial types solve this problem, because now you can augment the generated code in a separate file so that your changes aren’t lost when the wizard regenerates the code. For a great example of how partial types are used, look at the code automatically generated when you create a Windows Forms application using Visual Studio.
Source of Information : Apress Accelerated C Sharp 2010
more
Subscribe to:
Posts (Atom)
