Wednesday, 31 January 2007

Conversion in Custom Types

It is possible to define conversion operators for your own types in a number of ways. Which way depends on the type of conversion you want to perform.
  • Define conversion operators to simplify narrowing and widening conversions between numberic types.
  • Override ToString to provide conversion to strings, and override Parse to provide conversion from strings.
  • Implement System.IConvertable to enable conversion through System.Convert. Use this technique to enable culture-specific conversions.
  • Implement a TypeConverter class to enable design-time conversion for use in the Visual Studio Properties window.

Narrowing Conversion
If the range of precision of the source type exceeds that of the destination type, the operation is called a narrowing conversion, which will usually require an explicit conversion.

Widening Conversion
If the destination type can accomodate all possible values from the source type, that is known as a widening conversion and doesn't require an explicit cast.

Defining conversion operators allows you to directly assign from a value type to your custom type. Use the Widening/implicit keyword for conversions that don't loose precision; use the Narrowing/explicit keyword for conversions that could loose precision.

struct TypeA
{
public int
Value;

// Allows implicit conversion from an integer.

public static implicit operator TypeA(int arg)
{
TypeA res
= new
TypeA();
res.Value
=
arg;
return
res;
}

// Allows explicit conversion to an integer.

public static explicit operator int(TypeA arg)
{
return
arg.Value;
}

// Provides string conversion (avoids boxing).

public override string ToString()
{
return this
.Value.ToString();
}
}



public static void Main()
{
TypeA a;
int
i;

// Widening conversion is OK implicit.

a = 42;

// Narrowing conversion must be explicit.

i = (int)a;
// ..

Boxing & Unboxing

Boxing is the conversion of a value type to a reference type, and unboxing converts a reference type to a value type. This is best avoided for intensively repetitive tasks such as within foreach statements. The following tips are useful for avoiding uncessary boxing:
  • Implement type-specific versions (overloads) for procedures that accept various value types. It is better practice to create several overloaded procedures than one that accepts an Object argument.
  • Use generics whenever possible instead of accepting Object arguments.
  • Override the ToString, Equals, and GetHash virtual members when defining structures.

Tuesday, 30 January 2007

TypeForwardedTo

What is it?

Allow you to move a type from one assembly (assembly A) into another assembly (assembly B), and to do so in a way that it is not necessary to recompile clients that consume assembly A. Type forwarding works only for components referenced by existing applications. When you rebuild an application, there must be appropriate assembly references for any types used in the application.

There are four steps to forwarding a type:

  1. Move the source code for the type from the original assembly to the destination assembly.
  2. In the assembly where the type used was located, add a TypeForwardedToAttribute for the type that was moved.
  3. Compile the assembly that now contains the type.
  4. Recompile the assembly where the type used to be located, with a reference to the assembly that now contains the type.

Attribute declaration on the type being forwarded should look like the following

[assembly:TypeForwardedToAttribute(typeof(Example))]

Attributes

Attributes describe a type, method or property in a way that can be programmatically queried using Reflection. Common uses for Attributes include:

  • Specify which security privaledges a class requires
  • Specify security priviledges to refuse to reduce security risk
  • Declaring capabilities, such as supporting serialization
  • Describe the assembly by providing a title, description and copyright notice

Attributes all derieve from the System.Attribute class and are specified in C# using [] notation.

Constraints On Type Parameters

When defining a generic class, you are able to apply restrictions to the kinds of type that client code can use type arguments when it instatiates your class. If a client attempts to instantiate your class with a type that is not allowed by a constant, the result will be a compile-time error. There are six types of constraint available.

where T : struct
The type argument must be a value type. Any value type except Nullable can be specified.

where T : class
The type argument must be a reference type, including any class, interface, delegate, or array type.

where T : new()
The type argument must have a public parameterless constructor. When used in conjunction with other constraints, the new() constraint must be specified last.

where T : <base>
The type argument must be or derieve from the specified base class.

where T : <interface>
The type argument must be or implemented the specified interface. Multiple interface constraints can be specified. The constraining interface can also be generic.

where T : U
The type argument supplied for T must be or derieve from the argument supplied for U. This is called a naked type constraint.


class EmployeeList<T>
where T : Employee, IEmployee, System.IComparable
<T>, new
()
{
// ...

}
Applying constrains allows you to use methods on base types as you count on the type passed in supporting the method.  Within this generic code we are able to call methods specified by IEmployee because the generic type must implement IEmployee, removing this constraint and calling a method within IEmployee directly in the Generics code would lead to a compile time error. 

Generics

I am not going to even to attempt to fully cover Generics, I am guessing you can expect a great deal of questions on Generics in the exams. So I am going to cover some important stuff and leave links to the items that I have found useful.

Here goes with a simple generic's example ...

Lets say you want a collection of Person objects, a Person has a Forename & Surname property typically you would add these Person objects to an ArrayList.



static void Main(string[] args)
{
ArrayList people
= new
ArrayList();
people.Add(
new Person("Dave", "Green"
));
people.Add(
new Person("Joe", "Bloggs"
));
foreach (Person item in
people)
{
Console.WriteLine(
string.Format("{0} {1}"
, people.Forename, people.Surname));
}
}
Now this is not exactly type safe, we are assuming the ArrayList only contains Person objects, this case it does we added them but we can't always count on this. We are constantly casting & uncasting the objects, if dealing with value types we constantly box & unbox the objects in the list.

We somehow need to make the collection typed, enter generics ...

static void Main(string[] args)
{
List
<Person> people = new List<People>
();
people.Add(
new Person("Dave", "Green"
));
people.Add(
new Person("Joe", "Bloggs"
));
foreach (Person item in
people)
{
Console.WriteLine(
string.Format("{0} {1}"
, people.Forename, people.Surname));
}
}
Now you specify the type expected in the list on declaration and attempting to add the wrong type will cause a compile-time error.

Commonly Used Interfaces .NET Framework

Some commonly used interfaces in the .NET Framework

IComparable
Implemented by types whose values can be ordered; for example, the numeric and string classes. IComparable is required for sorting.


IDisposable
Defines methods for manually disposing of an object. This interface is important for large objects that consume resources, or objects that lock access to resources such as databases.


IConvertable
Enables a class to be converted to a base type such as Boolean, Byte, Double or String.


ICloneable
Supports copying an object.


IEquatable
Allows you to compare to instances of a class for equality. For example, if you implement this interface, you could say 'if (a == b)'


IFormattable
Enables you to convert the value of an object into a specially formatted string. This provides greater flexibility than the base.ToString method.

Interfaces

Interfaces define a contract (common set of methods that all classes that implement the interface must provide). For example IComparable interface defines the CompareTo method, allowing two instances of a class to be compared for equality.

An interface contains only signatures of methods, delegates or events. The implementation of the methods is done in the classes that implement the interface. An interface can be a member of a namespace or a class and can contain signatures of the following members: Methods, Properties, Indexers & Events.

An interface can inherit from one or more base interfaces. When a base type list contains a base class and interfaces, the base class must come first in the list.

A class that implements an interface can explicitly implement members of that interface. An explicitly implemented member cannot be accessed through a class instance, but only through an instance of the interface.


interface IControl
{
void
Paint();
}
interface
ISurface
{
void
Paint();
}

class
SampleClass : IControl, ISurface
{
public void
Paint()
{
}
}
Both IControl & ISurface will point to the same implementation this cause problems if the implementation needs to be different for each of the interfaces. You can explicitly define the interface implementation if this is the case. This method can only be called through the interface and is accomplished by naming the class member with the name of the interface and a period.

class SampleClass : IControl, ISurface
{
public void
IControl.Paint()
{
}
public void
ISurface.Paint()
{
}
}

Monday, 29 January 2007

Reference Types Useful Links

Useful links for more information on reference types.
MSDN Reference Types
WIKI Books - Reference Types

Keywords used to declare Reference Types

The following keywords can be used to declare reference types.
  • class
  • interface
  • delegate

System.ValueType & System.Object

Every value type derieves from System.ValueType and all reference types derieve from System.Object, BUT not all System.Object types are reference types as System.ValueType also derieves from System.Object as does every object in the .NET Framework.

Common Reference Types

Most types within the .NET Framework are reference types, in fact about 2500 reference types are available. Reference type store the address of the data in the stack, also known as a pointer & the actual data of the object is stored on the heap. When no more pointers point to the data on the heap the object is eligable for garbage collection.

Garbage collection will only occur when needed or when triggered by a call to GC.Collect. Automatic garbage collection is optimised for applications where most instances are short-lived, except for those allocated at the beginning of the application.

Everything not derieved from System.ValueType is a reference type, the most commonly used reference types are listed below.


  • System.Object
  • System.String
  • System.Text.StringBuilder
  • System.Array
  • System.IO.Stream
  • System.Exception

Reference types are more than containers for data, they provide means to manipulate their members, System.String provides a set of members for working with text.

System.String class in .NET is immutable, meaning changes to a string instance causes the runtime to create a new string instance and abandon the old one. This happens behind the scenes this has the following implications.

string s = "first entry";    
s += " second entry";
s += " third entry";
s += " fourth entry";
Only the last string has a reference, the first three entries will be disposed of  during garbage collection.  To avoid unnecessary garbage collection you can do one of several things.
  • Use the String class's Concat, Join, or Format methods to join multiple items in a single statement
  • Use the StringBuilder class to create dynamic (mutable) strings.

The System.Array class can be used to Sort items, as with the System.String type, System.Array provides members for working with its contained data.

int[] a = {3, 5, 6, 4 };
Array.Sort(a);
Streams are another very common type they provide a means for reading and writing to the disk and communicating across the network.  The System.IO.Stream type is the base type for all task specific stream types.  The most common stream classes are shown below.
FileStream
Create a base stream used to write or read from a file
MemoryStream
Create a base stream used to write or read from memory
StreamReader
Read data from the stream
StreamWriter
Write data to the stream
Simplest of the stream classes is the StreamReader & StreamWriter classes.  You can pass a filename to the constructor enabling you to read or write to a file.  After processing the file you call the Close method on the stream to release the lock on the file.

 
StreamReader sr = new StreamReader(filename);
Console.WriteLine(sr.ReadToEnd());
sr.Close();

Sunday, 28 January 2007

Nullable Types

Conventially it was not possible to set a System.ValueType to null, when the Constructor runs it defaults the value of a System.ValueType. Typically this does not cause a problem until you start interacting with a database for example, which does allow nulls. When this happens I have conventially used code like the following to determine whether a System.ValueType has a value or not.


if (myInt != int.MinValue)
{
// Int has been set.

}
if (myDateTime !=
DateTime.MinValue)
{
// DateTime has been set.

}
An alternative now exists with nullable types, nullable types are instances of the System.Nullable struct. A nullable type can represent the normal range of values for its underlying type, plus an additional null value. How to declare nullable type of type Int32, both of the following declarations compile to the same IL code.


int? a = null;
Nullable
<int> a = null;
You can determine whether a nullable type has a value by using the HasValue property, you can also return the value using the Value property if no value is assigned calling this method will result in a System.InvalidOperationException.

If you wish to default the value of a nullable type when reading its value you can use the null coalescing operator, this can also be used with value types.


int? a = null;
Console.WriteLine(a
?? -1);
The code above defaults the value of a when null to -1, which is very like the statement below but a great deal neater.

int? a = null;
Console.WriteLine(a
== null ? -1 : a);

Structs Implementing an Interface

If a Struct is a ValueType and an Interface a ReferenceType and we know the contents of a variable is copied when copying a ValueType and the reference to the object is copied when copying a ReferenceType, what happens when we make a Struct implement an Interface?

public class MyClass



{



interface
ICustomValueType



{



int CustomVariable1 { get; set
; }



}







struct
MyValueType : ICustomValueType



{



public int
CustomVariable1



{



get { return
_customVariable1; }



set { _customVariable1 =
value; }



}
private int
_customVariable1;



}







public static void
Main()



{



// Direct reference to Value Type.




MyValueType valueType1 = new MyValueType();



valueType1.CustomVariable1
= 1
;







MyValueType valueType2
= new
MyValueType();



valueType2.CustomVariable1
= 2
;







Console.WriteLine(
"Value Type 1 = {0}"
, valueType1.CustomVariable1);



Console.WriteLine(
"Value Type 2 = {0}"
, valueType2.CustomVariable1);







valueType2
=
valueType1;



valueType1.CustomVariable1
= 5
;



Console.WriteLine(
"Value Type 1 = {0}"
, valueType1.CustomVariable1);



Console.WriteLine(
"Value Type 2 = {0}"
, valueType2.CustomVariable1);







// Reference to ICustomValueType.




ICustomValueType interfaceValueType1 = new MyValueType();



interfaceValueType1.CustomVariable1
= 1
;







ICustomValueType interfaceValueType2
= new
MyValueType();



interfaceValueType2.CustomVariable1
= 2
;







Console.WriteLine(
"Value Type 1 = {0}"
, interfaceValueType1.CustomVariable1);



Console.WriteLine(
"Value Type 2 = {0}"
, interfaceValueType2.CustomVariable1);







valueType2
=
valueType1;



valueType1.CustomVariable1
= 5
;



Console.WriteLine(
"Value Type 1 = {0}"
, valueType1.CustomVariable1);



Console.WriteLine(
"Value Type 2 = {0}"
, valueType2.CustomVariable1);



}



}
 
 
 
When interacting with the ValueType directly it acts like a ValueType and the variable is copied from the Stack.  When referencing the Interface the reference to the variable is copied and changing the value of one causes both instances to change. 

Value Types

Value types are derieved from two main categories Structs & Enumerations.
Structs fall into the following categories
- Integral types
- Floating-point types
- decimal
- bool
- User defined structs
Value types are contained on the stack , assigning one value type variable to another copies the
contained value. This differs from reference types, which are stored on the managed heap and
copying a reference type copies the reference to the object but not the object itself.
Console.WriteLine("a = {0}", a);
Console.WriteLine(
"b = {0}", b);

a
= b;
b
= 4;

Console.WriteLine(
"a = {0}", a);
Console.WriteLine(
"b = {0}", b);



The variable a starts off with a value of 1 and b with a value of 2.
The contents of variable b are copied to a and variable b set to 4.
However changing variable b does not affect variable a, which has
a copy of the contents of variable b.

All value types are derieved from System.ValueType one interesting type is System.String this doesn't derieve from System.ValueType but acts like a value type, it is immutable a new instance is created
each time it is changed unlike other reference types.
string a = "first string";
string b = "second string";
Console.WriteLine(
"string a = {0}", a);
Console.WriteLine(
"string b = {0}", b);

b
= a;
a
= "modified string a";
Console.WriteLine(
"string a = {0}", a);
Console.WriteLine(
"string b = {0}", b);
Unlike reference types, it is not possible to derieve a new type from a value type.  However, like reference types, structs can implement interfaces.

Saturday, 27 January 2007

Exam 70-536 - First Look

I am going to start off looking at the following areas, and produce a number of articles on each of the topics that I cover.

Manage data in .NET Framework application by using the .NET Framework 2.0 system types

  • Value Types
  • Nullable Types
  • Reference Types
  • Attributes
  • Generic Types Exception Classes
  • Boxing and Unboxing
  • TypeForwardedToAttribute Class

Implement .NET Framework interfaces to cause components to comply with standard contracts.

  • IComparible interface
  • IDisposable interface
  • IConvertible interface
  • ICloneable interface
  • IEquatable interface
  • IFormattable interface

Control interactions between .NET Framework application components by using events and delegates.

  • Delegate class
  • EventArgs class
  • EventHandler delegates

Microsoft Certified Technology Specialist

Why the blog? Simple, decided to study for my Microsoft exams 'Microsoft Certified Technology Specialist' (MCTS) seems as good as place as any to start, so I have decided to blog my progress.

I am going to start with Exam 70-536: TS: Microsoft .NET Framework 2.0 - Application Development Foundation. I intend on documenting the requirements and the research I have done on each of them and let you know how I do on the exams.

About me ...
I have been a C# developer for 5 years, starting in the insurance industry before moving to a Sage Reseller I am now working for .com company.