Sunday, September 18, 2011
Code Shortcuts in Visual Studio 2010
~ + tab tab
Code snippet:
~_Default()
{
}
2. To create an Attribute
attribute + tab tab
Code snippet:
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
sealed class MyAttribute : Attribute
{
// See the attribute guidelines at
// http://go.microsoft.com/fwlink/?LinkId=85236
readonly string positionalString;
// This is a positional argument
public MyAttribute(string positionalString)
{
this.positionalString = positionalString;
// TODO: Implement code here
throw new NotImplementedException();
}
public string PositionalString
{
get { return positionalString; }
}
// This is a named argument
public int NamedInt { get; set; }
}
3. Checked keyword
checked + tab tab
Code snippet:
checked
{
}
4. Creating a Class
class + tab tab
Code snippet:
class MyClass
{
}
5. Creating a Constructor
ctor + tab tab
Code snippet:
public _Default()
{ }
6. Console.WriteLine() shortcut
cw + tab tab
Code snippet:
Console.WriteLine ();
7. Do…..while loop
do + tab tab
Code snippet:
do
{
} while (true);
8. Else statement
else + tab tab
Code snippet:
else
{}
9. Enum
enum + tab tab
Code snippet:
enum MyEnum
{
}
10. Equals
equals +tab tab
Code snippet:
// override object.Equals
public override bool Equals(object obj)
{
//
// See the full list of guidelines at
// http://go.microsoft.com/fwlink/?LinkID=85237
// and also the guidance for operator== at
// http://go.microsoft.com/fwlink/?LinkId=85238
//
if (obj == null || GetType() != obj.GetType())
{
return false;
}
// TODO: write your implementation of Equals() here
throw new NotImplementedException();
return base.Equals(obj);
}
// override object.GetHashCode
public override int GetHashCode()
{
// TODO: write your implementation of GetHashCode() here
throw new NotImplementedException();
return base.GetHashCode();
}
11. Exceptions
exceptions + tab tab
Code snippet:
[Serializable]
public class MyException : Exception
{
public MyException() { }
public MyException(string message) : base(message) { }
public MyException(string message, Exception inner) : base(message, inner)
}
protected MyException
(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}
12. For loop
for + tab tab
Code snippet:
for (int i = 0; i < length; i++)
{
}
13. Foreach loop
foreach + tab tab
Code snippet:
foreach (var item in collection)
{
}
14. Reverse for loop
for + tab tab
Code snippet:
for (int i = length - 1; i >= 0 ; i--)
{
}
15. If statement
if + tab tab
Code snippet:
if (true)
{
}
16. Indexer
indexer + tab tab
Code snippet:
public object this[int index]
{
get { /* return the specified index here */ }
set { /* set the specified index to value here */ }
}
17. Interface
interface + tab + tab
Code snippet:
interface IInterface
{
}
18. Invoke- to safely invoke the event
invoke + tab tab
Code snippet:
EventHandler temp = MyEvent;
if (temp != null)
{
temp();
}
19. Iterator- simple iterator
iterator + tab tab
Code snippet:
public System.Collections.Generic.IEnumerator GetEnumerator()
{
throw new NotImplementedException();
yield return default(ElementType);
}
20. Iterator – complex iterator
iterindex + tab tab
Code snippet:
public MyViewIterator MyView
{
get
{
return new MyViewIterator(this);
}
}
public class MyViewIterator
{
readonly _Default outer;
internal MyViewIterator(_Default outer)
{
this.outer = outer;
}
// TODO: provide an appropriate implementation here
public int Length { get { return 1; } }
public ElementType this[int index]
{
get
{
//
// TODO: implement indexer here
//
// you have full access to _Default privates
//
throw new NotImplementedException();
return default(ElementType);
}
}
public System.Collections.Generic.IEnumerator GetEnumerator()
{
for (int i = 0; i < this.Length; i++)
{
yield return this[i];
}
}
}
21. Lock statement
lock + tab tab
Code snippet:
lock (this)
{}
22. To Show the Message box in ASP.Net/Console Application
mbox + tab tab
Code snippet:
global::System.Windows.Forms.MessageBox.Show("hello");
23. Action
mvcaction +tab tab
Code snippet:
public ActionResult Action()
{
return View();
}
24. Action via http post method
mvcpostaction + tab tab
Code snippet:
[HttpPost]
public ActionResult Action()
{
return View();
}
25. For Namespace
namespace + tab tab
Code snippet:
namespace MyNamespace
{
}
26. Creating Property
prop + tab tab
Code snippet:
public int MyProperty { get; set; }
27. Attached dependency property
propa + tab tab
Code snippet:
public static int GetMyProperty(DependencyObject obj)
{
return (int)obj.GetValue(MyPropertyProperty);
}
public static void SetMyProperty(DependencyObject obj, int value)
{
obj.SetValue(MyPropertyProperty, value);
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.RegisterAttached("MyProperty", typeof(int), typeof(ownerclass), new UIPropertyMetadata(0));
28. Dependency property as a backing store
propdp + tab tab
Code snippet:
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(ownerclass), new UIPropertyMetadata(0));
29. Property with full description
propfull + tab tab
Code snippet:
private int myVar;
public int MyProperty
{
get { return myVar;}
set { myVar = value;}
}
30. Auto implemented property with get accessor as private
propg + tab tab
Code snippet:
public int MyProperty { get; set; }
31. For int Main method
sim + tab tab
Code snippet:
static int Main(string[] args)
{
return 0;
}
32. Create structure
struct + tab tab
Code snippet:
struct MyStruct
{
}
33. Void Main method
svm + tab tab
Code snippet:
static void Main(string[] args)
{}
34. Switch stamen
switch + tab tab
Code snippet:
switch (switch_on)
{
default:
}
35. Test class
testc + tab tab
Code snippet:
[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestClass]
public class MyTestClass
{
}
36. Test method
testm + tab tab
Code snippet:
[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod]
public void MyTestMethod()
{
}
37. Try..catch
try + tab tab
Code snippet:
try
{}
catch (Exception)
{
throw;
}
38. Try..finally
tryf + tab tab
Code snippet:
try
{}
catch (Exception)
{
throw;
}
39. Unchecked statement
unchecked + tab tab
Code snippet:
unchecked
{
}
40. Unsafe statement
unsafe + tab tab
Code snippet:
unsafe
{
}
41. Using statement
using + tab tab
Code snippet:
using (resource)
{
}
42. Dependency property event handler in windows work flow application
wde + tab tab
Code snippet:
public static global::System.Workflow.ComponentModel.DependencyProperty InvokeEvent = global::System.Workflow.ComponentModel.DependencyProperty.Register("Invoke", typeof(EventHandler), typeof(_Default));
[System.ComponentModel.Description("Invoke")]
[System.ComponentModel.Category("Invoke Category")]
[System.ComponentModel.Browsable(true)]
[System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible)]
public event EventHandler Invoke
{
add
{
base.AddHandler(_Default.InvokeEvent, value);
}
remove
{
base.RemoveHandler(_Default.InvokeEvent, value);
}
}
43. Dependency property in windows work-flow application
wdp + tab tab
Code snippet:
public static global::System.Workflow.ComponentModel.DependencyProperty MyPropertyProperty = global::System.Workflow.ComponentModel.DependencyProperty.Register("MyProperty", typeof(string), typeof(_Default));
[System.ComponentModel.Description("MyProperty")]
[System.ComponentModel.Category("MyProperty Category")]
[System.ComponentModel.Browsable(true)]
System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible)]
public string MyProperty
{
get
{
return ((string)(base.GetValue(_Default.MyPropertyProperty)));
}
set
{
base.SetValue(_Default.MyPropertyProperty, value);
}
}
44. While loop
while + tab tab
Code snippet:
while (true)
{
}
Saturday, September 3, 2011
Inheritance
using System;
public class ParentClass
{
public ParentClass()
{
Console.WriteLine("Parent Constructor.");
}
public void print()
{
Console.WriteLine("I'm a Parent Class.");
}
}
public class ChildClass : ParentClass
{
public ChildClass()
{
Console.WriteLine("Child Constructor.");
}
public static void Main()
{
ChildClass child = new ChildClass();
child.print();
}
}
Output:
Parent Constructor.
Child Constructor.
I'm a Parent Class.Listing 8-1 shows two classes. The top class is named ParentClass and the main class is called ChildClass. What we want to do is create a child class, using existing code fromParentClass.
First we must declare our intention to use ParentClass as the base class of ChildClass. This is accomplished through the ChildClass declaration public class ChildClass : ParentClass. The base class is specified by adding a colon, ":", after the derived class identifier and then specifying the base class name.
Note: C# supports single class inheritance only. Therefore, you can specify only one base class to inherit from. However, it does allow multiple interface inheritance, a subject covered in a later lesson.
ChildClass has exactly the same capabilities as ParentClass. Because of this, you can also say ChildClass "is" a ParentClass. This is shown in the Main() method of ChildClass when theprint() method is called. ChildClass does not have its own print() method, so it uses the ParentClass print() method. You can see the results in the 3rd line of output.
Base classes are automatically instantiated before derived classes. Notice the output from Listing 8-1. The ParentClass constructor executed before the ChildClass constructor.
Listing 8-2. Derived Class Communicating with Base Class: BaseTalk.cs
using System;
public class Parent
{
string parentString;
public Parent()
{
Console.WriteLine("Parent Constructor.");
}
public Parent(string myString)
{
parentString = myString;
Console.WriteLine(parentString);
}
public void print()
{
Console.WriteLine("I'm a Parent Class.");
}
}
public class Child : Parent
{
public Child() : base("From Derived")
{
Console.WriteLine("Child Constructor.");
}
public new void print()
{
base.print();
Console.WriteLine("I'm a Child Class.");
}
public static void Main()
{
Child child = new Child();
child.print();
((Parent)child).print();
}
}
Output:
From Derived
Child Constructor.
I'm a Parent Class.
I'm a Child Class.
I'm a Parent Class.Derived classes can communicate with base classes during instantiation. Listing 8-2 shows how this is done at the child constructor declaration. The colon, ":", and keyword base call the base class constructor with the matching parameter list. If the code had not appended base("From Derived") to the Derived constructor, the code would have automatically calledParent(). The first line of output shows the base class constructor being called with the string "From Derived".
Sometimes you may want to create your own implementation of a method that exists in a base class. The Child class does this by declaring its own print() method. The Child print()method hides the Parent print() method. The effect is the Parent print() method will not be called, unless we do something special to make sure it is called.
Inside the Child print() method, we explicitly call the Parent print() method. This is done by prefixing the method name with "base.". Using the base keyword, you can access any of a base class public or protected class members. The output from the Child print() method is on output lines 3 and 4.
Another way to access base class members is through an explicit cast. This is done in the last statement of the Child class Main() method. Remember that a derived class is a specialization of its base class. This fact allows us to perform a cast on the derived class, making it an instance of its base class. The last line of output from Listing 8-2 shows the Parentprint() method was indeed executed.
Notice the new modifier on the Child class print() method. This enables this method to hide the Parent class print() method and explicitly states your intention that you don't want polymorphism to occur. Without the new modifier, the compiler will produce a warning to draw your attention to this.
class Animal
{
public Animal()
{
HttpContext.Current.Response.Write("Animal constructor");
}
public void Greet()
{
HttpContext.Current.Response.Write("Animal says Hello");
}
public void Talk()
{
HttpContext.Current.Response.Write("Animal talk");
}
public virtual void Sing()
{
HttpContext.Current.Response.Write("Animal song");
}
}
class Dog : Animal
{
public Dog()
{
HttpContext.Current.Response.Write("Dog constructor");
}
public new void Talk()
{
HttpContext.Current.Response.Write("Dog talk");
}
public override void Sing()
{
HttpContext.Current.Response.Write("Dog song");
}
public static void Main()
{
Animal a2 = new Dog();
a2.Talk();
a2.Sing();
a2.Greet();
}
}
We have an object of type Animal, but it references an object of type Dog.
Thus you can see the base class constructor getting called first followed by the derived class constructor.
Now we call Talk() and find that the method that's executed is the base class method.
That's not surprising when you consider that the object was declared to be of the base type which in our case is Animal.
Now when we call Sing(), we find that the derived class method has got called.
This is because in the base class the method is prototyped as public virtual void Sing() and in the derived class we have overridden it by using public override void Sing().
In C#, we need to explicitly use the override keyword as opposed to C++ where we didn't have to do that.
And finally when we call Greet() the base class method gets called and this is not confusing at all specially since the derived class has not even implemented the method.
class Color
{
public virtual void Fill()
{
HttpContext.Current.Response.Write("Fill me up with color");
}
public void Fill(string s)
{
HttpContext.Current.Response.Write("Fill me up with " + s);
}
}
class Green : Color
{
public override void Fill()
{
HttpContext.Current.Response.Write("Fill me up with green");
}
public static void Main()
{
Green g1 = new Green();
g1.Fill();
g1.Fill("violet");
}
}
---------------------------------------------------
class Software
{
public Software()
{
m_x = 100;
}
public Software(int y)
{
m_x = y;
}
protected int m_x;
}
class MicrosoftSoftware : Software
{
public MicrosoftSoftware()
{
HttpContext.Current.Response.Write(m_x + "
");
}
}
class AstuteSoftware : Software
{
//Here I am telling the compiler which
//overload of the base constructor to call
public AstuteSoftware(int y)
: base(y)
{
HttpContext.Current.Response.Write(m_x + "
");
}
//Here we are telling the compiler to first
//call the other overload of the constructor
public AstuteSoftware(string s, int f)
: this(f)
{
HttpContext.Current.Response.Write(s + "
");
}
}
protected void Page_Load(object sender, EventArgs e)
{
MicrosoftSoftware m1 = new MicrosoftSoftware();
//MicrosoftSoftware m2 = new MicrosoftSoftware(300); will not compile
AstuteSoftware du1 = new AstuteSoftware(50); // 50
AstuteSoftware du2 = new AstuteSoftware("test", 75); // 75 test
}
MicrosoftSoftware m2 = new MicrosoftSoftware(300); will not compile
The base class had two overloaded constructors. One that took zero arguments and one that took an int.
In the derived class we only have the zero argument constructor. Constructors are not inherited by derived classes.
Thus we cannot instantiate a derived class object using the constructor that takes an int as parameter.
As you will deduce from the output we got, the base class constructor that called was the default parameter-less constructor.
Now take a look at this second derived class.
Download Code
Dispose vs Finalize
Finalization is the process by which the GC allows objects to clean up any unmanaged resources that they're holding, before the actually destroying the instance. An implementation of the Finalize method is called a "finalizer." Finalizers should free only external resources held directly by the object itself. The GC attempts to call finalizers on objects when it finds that the object is no longer in use—when no other object is holding a valid reference to it. In other words, finalizers are methods that the GC calls on "seemingly dead objects" before it reclaims memory for that object.
The GC calls an object's finalizer automatically, typically once per instance—although that's not always the case (see the Author's Note below for more information). The framework calls finalizers on a secondary thread handled by the GC. You should never rely on finalizers to clean up managed resources. A class that has no finalizer implemented but is holding references to unmanaged objects can cause memory leaks, because the resources might become orphaned if a class instance is destroyed before releasing the unmanaged objects.
| Author's Note: Although the GC usually calls an object's finalizer only once, you can change that by writing code to re-register the instance using theReRegisterForFinalize method and not subsequently calling the GC.SuppressFinalize method on the instance. |
You must implement finalizers very carefully; it's a complex operation that can carry considerable performance overhead. The performance overhead stems from the fact that finalizable objects are enlisted and removed from the finalization queues, which are internal data structures containing pointers to instances of classes that implement a finalizer method. When pointers to these objects are placed in this data structure, the object is said to be enlisted in the Finalization Queue. Note that the GC periodically scans this data structure to locate these pointers. When it finds one, it removes the pointer from the queue and appends the pointer at the end of another queue called the freachable queue.
Further, finalizable objects tend to get promoted to the higher generations and hence stay in memory for a relatively longer period of time. Note that the GC works more frequently in the lower generations than in the higher ones.
The time and order of execution of finalizers cannot be predicted or pre-determined. This is why you'll hear that the nature of finalization is "non-deterministic." Further, due to the non-deterministic nature of finalization the framework does not and cannot guarantee that the Finalize method will ever be called on an instance. Hence, you cannot rely upon this method to free up any un-managed resources (such as a file handle or a database connection instance) that would otherwise not be garbage collected by the GC.
Note that you cannot call or override the Finalize method. It is generated implicitly if you have a destructor for the class. This is shown in the following piece of C# code:—
class Test { // Some Code ~Test { //Necessary cleanup code } } In the preceding code, the ~Test syntax declares an explicit destructor in C#, letting you write explicit cleanup code that will run during the finalize operation.
The framework implicitly translates the explicit destructor to create a call to Finalize:
protected override void Finalize() { try { //Necessary cleanup code } finally { base.Finalize(); } } Note that the generated code above calls the base.Finalize method.
You should note the following points should when implementing finalizers:
- Finalizers should always be protected, not public or private so that the method cannot be called from the application's code directly and at the same time, it can make a call to the base.Finalize method
- Finalizers should release unmanaged resources only.
- The framework does not guarantee that a finalizer will execute at all on any given instance.
- Never allocate memory in finalizers or call virtual methods from finalizers.
- Avoid synchronization and raising unhandled exceptions in the finalizers.
- The execution order of finalizers is non-deterministic—in other words, you can't rely on another object still being available within your finalizer.
- Do not define finalizers on value types.
- Don't create empty destructors. In other words, you should never explicitly define a destructor unless your class needs to clean up unmanaged resources—and if you do define one, it should do some work. If, later, you no longer need to clean up unmanaged resources in the destructor, remove it altogether.
Unlike Finalize, developers should call Dispose explicitly to free unmanaged resources. In fact, you should call the Dispose method explicitly on any object that implements it to free any unmanaged resources for which the object may be holding references. The Dispose method generally doesn't free managed memory—typically, it's used for early reclamation of only the unmanaged resources to which a class is holding references. In other words, this method can release the unmanaged resources in a deterministic fashion.
Note that an object should implement IDisposable and the Dispose method not only when it must explicitly free unmanaged resources, but also when it instantiates managed classes which in turn use such unmanaged resources. Implementing IDisposable is a good choice when you want your code, not the GC, to decide when to clean up resources. Further, note that the Dispose method should not be called concurrently from two or more different threads as it might lead to unpredictable results if other threads still have access to unmanaged resources belonging to the instance.
The IDisposable interface consists of only one Dispose method with no arguments.
public interface IDisposable { void Dispose(); } The following code illustrates how to implement the Dispose method on a class that implements the IDisposable interface:
class Test : IDisposable { private bool isDisposed = false; ~Test() { Dispose(false); } protected void Dispose(bool disposing) { if (disposing) { // Code to dispose the managed resources of the class } // Code to dispose the un-managed resources of the class isDisposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } } In the preceding code, when the Boolean variable disposed equals true, the object can free both managed and unmanaged resources; but if the value equals false, the call has been initiated from within the finalizer (~Test) in which case the object should release only the unmanaged resources that the instance has reference to.
The Dispose/Finalize Pattern
Microsoft recommends that you implement both Dispose and Finalize when working with unmanaged resources. The correct sequence then would be for a developer to callDispose. The Finalize implementation would run and the resources would still be released when the object is garbage collected even if a developer neglected to call the Disposemethod explicitly. Francesco Balena writes in his blog "the Dispose/Finalize pattern should be used only when your type invokes unmanaged code that allocates unmanaged resources (including unmanaged memory) and returns a handle that you must use eventually to release the resource. Both dispose and finalize must chain up to their parent objects by calling their parent's respective methods after they have disposed or finalized their own members".
Simply put, cleanup the unmanaged resources in the Finalize method and the managed ones in the Dispose method, when the Dispose/Finalize pattern has been used in your code.
As an example, consider a class that holds a database connection instance. A developer can call Dispose on an instance of this class to release the memory resource held by the database connection object. After it is freed, the Finalize method can be called when the class instance needs to be released from the memory. According to MSDN, "Finalizeprovides a backup to prevent resources from permanently leaking if the programmer fails to call Dispose".
After the Dispose method has been called on an object, you should suppress calls to the Finalize method by invoking the GCThe following code illustrates how to implement both the Dispose and Finalize pattern for a class.
public class Base: IDisposable { private bool isDisposed = false; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if(!isDisposed) { if (disposing) { // Code to dispose the managed resources // held by the class } } // Code to dispose the unmanaged resources // held by the class isDisposed = true; base.Dispose(disposing); } ~Base() { Dispose (false); } } You should not reimplement IDisposable for a class that inherits from a base class in which IDispose has already been implemented. The following code snippet may help you understand this concept:
public class Base: IDisposable { private bool isDisposed = false; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if(!isDisposed) { if (disposing) { // Code to dispose managed resources // held by the class } } // Code to dispose unmanaged resources // held by the class isDisposed = true; base.Dispose(disposing); } ~Base() { Dispose (false); } } public class Derived: Base { protected override void Dispose(bool disposing) { if (disposing) { // Code to cleanup managed resources held by the class. } // Code to cleanup unmanaged resources held by the class. base.Dispose(disposing); } // Note that the derived class does not // re-implement IDisposable } In the preceding code, what if the Dispose method were to throw an exception? In that case, the Finalize method would exit prematurely, and the memory would never be reclaimed. Hence, in such situations, it is advisable to wrap the Dispose method in a try-catch block. This will prevent finalization exceptions from orphaning the object.
Note the following points when implementing disposable types:
- Implement IDisposable on every type that has a finalizer
- Ensure that an object is made unusable after making a call to the Dispose method. In other words, avoid using an object after the Dispose method has been called on it.
- Call Dispose on all IDisposable types once you are done with them
- Allow Dispose to be called multiple times without raising errors.
- Suppress later calls to the finalizer from within the Dispose method using the GC.SuppressFinalize method
- Avoid creating disposable value types
- Avoid throwing exceptions from within Dispose methods
In some cases, you might want to provide programmers using an object with the ability to explicitly release these external resources before the garbage collector frees the object. If an external resource is scarce or expensive, better performance can be achieved if the programmer explicitly releases resources when they are no longer being used. To provide explicit control, implement the Dispose Method provided by theIDisposable Interface. The consumer of the object should call this method when it is finished using the object. Dispose can be called even if other references to the object are alive.
Note that even when you provide explicit control using Dispose, you should provide implicit cleanup using the Finalize method. Finalize provides a backup to prevent resources from permanently leaking if the programmer fails to call Dispose.
For more information about implementing Finalize and Dispose to clean up unmanaged resources, see Garbage Collection. The following code example illustrates the basic design pattern for implementingDispose .
Friday, September 2, 2011
Value vs Reference Types
One area likely to cause confusion for those coming from a Java or VB6 background is the distinction between value types and reference types in C#. In particular, C# provides two types—class and struct, which are almost the same except that one is a reference type while the other is a value type. This article explores their essential differences, and the practical implications when programming in C#.
This article assumes you have a basic knowledge of C#, and are able to define classes and properties.
First, What Are Structs?
Put simply, structs are cut-down classes. Imagine classes that don’t support inheritance or finalizers, and you have the cut-down version: the struct. Structs are defined in the same way as classes (except with the struct keyword), and apart from the limitations just described, structs can have the same rich members, including fields, methods, properties and operators. Here’s a simple struct declaration:
struct Point
{
private int x, y; // private fields
public Point (int x, int y) // constructor
{
this.x = x;
this.y = y;
}
public int X // property
{
get {return x;}
set {x = value;}
}
public int Y
{
get {return y;}
set {y = value;}
}
}
What is a Reference Type?
Reference types store the address of their data, also known as a pointer, on the stack. The actual data that the address refers to is stored in an area of memory called the heap. Because reference types represent the address of the data rather than the data itself, assigning a reference variable to another doesn’t copy the data. Instead, assigning a reference variable to another instance creates a second copy of the reference, which refers to the same location of the heap as the original value:
using System; struct Struct1 { public int Value; } class Class1 { public int Value = 0; } class Test { static void Main() { Struct1 v1 = new Struct1(); Struct1 v2 = v1; v2.Value = 123; Class1 r1 = new Class1(); Class1 r2 = r1; r2.Value = 123; Console.WriteLine("Values: {0}, {1}", v1.Value, v2.Value); Console.WriteLine("Refs: {0}, {1}", r1.Value, r2.Value); } }Here is the output:c:\Windows\Microsoft.NET\Framework\v2.0.50727>ref.exe Values: 0, 123 Refs: 123, 123Value and Reference Types
There is another difference between structs and classes, and this is also the most important to understand. Structs are value types, while classes are reference types, and the runtime deals with the two in different ways. When a value-type instance is created, a single space in memory is allocated to store the value. Primitive types such as int, float, bool and char are also value types, and work in the same way. When the runtime deals with a value type, it's dealing directly with its underlying data and this can be very efficient, particularly with primitive types.
With reference types, however, an object is created in memory, and then handled through a separate reference—rather like a pointer. Suppose Point is a struct, and Form is a class. We can instantiate each as follows:
Point p1 = new Point(); // Point is a *struct*
Form f1 = new Form(); // Form is a *class*
In the first case, one space in memory is allocated for p1, wheras in the second case, two spaces are allocated: one for a Form object and another for its reference (f1). It's clearer when we go about it the long way:
Form f1; // Allocate the reference
f1 = new Form(); // Allocate the object
If we copy the objects to new variables:
Point p2 = p1;
Form f2 = f1;
p2, being a struct, becomes an independent copy of p1, with its own separate fields. But in the case of f2, all we’ve copied is a reference, with the result that both f1 and f2 point to the same object.
This is of particular interest when passing parameters to methods. In C#, parameters are (by default) passed by value, meaning that they are implicitly copied when passed to the method. For value-type parameters, this means physically copying the instance (in the same way p2 was copied), while for reference-types it means copying a reference (in the same way f2 was copied). Here is an example:
Point myPoint = new Point (0, 0); // a new value-type variable
Form myForm = new Form(); // a new reference-type variable
Test (myPoint, myForm); // Test is a method defined below
void Test (Point p, Form f)
{
p.X = 100; // No effect on MyPoint since p is a copy
f.Text = "Hello, World!"; // This will change myForm’s caption since
// myForm and f point to the same object
f = null; // No effect on myForm
}
Assigning null to f has no effect because f is a copy of a reference, and we’ve only erased the copy.
We can change the way parameters are marshalled with the ref modifier. When passing by “reference”, the method interacts directly with the caller’s arguments. In the example below, you can think of the parameters p and f being replaced by myPoint and myForm:
Point myPoint = new Point (0, 0); // a new value-type variable
Form myForm = new Form(); // a new reference-type variable
Test (ref myPoint, ref myForm); // pass myPoint and myForm by reference
void Test (ref Point p, ref Form f)
{
p.X = 100; // This will change myPoint’s position
f.Text = “Hello, World!”; // This will change MyForm’s caption
f = null; // This will nuke the myForm variable!
}
In this case, assigning null to f also makes myForm null, because this time we’re dealing with the original reference variable and not a copy of it.
Memory Allocation
The Common Language Runtime allocates memory for objects in two places: the stack and the heap. The stack is a simple first-in last-out memory structure, and is highly efficient. When a method is invoked, the CLR bookmarks the top of the stack. The method then pushes data onto the stack as it executes. When the method completes, the CLR just resets the stack to its previous bookmark—“popping” all the method’s memory allocations is one simple operation!
In contrast, the heap can be pictured as a random jumble of objects. Its advantage is that it allows objects to be allocated or deallocated in a random order. As we’ll see later, the heap requires the overhead of a memory manager and garbage collector to keep things in order.
To illustrate how the stack and heap are used, consider the following method:
void CreateNewTextBox()
{
TextBox myTextBox = new TextBox(); // TextBox is a class
}
In this method, we create a local variable that references an object. The local variable is stored on the stack, while the object itself is stored on the heap:
The stack is always used to store the following two things:
- The reference portion of reference-typed local variables and parameters (such as the myTextBox reference)
- Value-typed local variables and method parameters (structs, as well as integers, bools, chars, DateTimes, etc.)
The following data is stored on the heap:
- The content of reference-type objects.
- Anything structured inside a reference-type object.
Memory Disposal
Once CreateNewTextBox has finished running, its local stack-allocated variable, myTextBox, will disappear from scope and be “popped” off the stack. However, what will happen to the now-orphaned object on the heap to which it was pointing? The answer is that we can ignore it—the Common Language Runtime’s garbage collector will catch up with it some time later and automatically deallocate it from the heap. The garbage collector will know to delete it, because the object has no valid referee (one whose chain of reference originates back to a stack-allocated object). C++ programmers may be a bit uncomfortable with this and may want to delete the object anyway (just to be sure!) but in fact there is no way to delete the object explicitly. We have to rely on the CLR for memory disposal—and indeed, the whole .NET framework does just that!
However there is a caveat on automatic destruction. Objects that have allocated resources other than memory (in particular “handles”, such as Windows handles, file handles and SQL handles) need to be told explicitly to release those resources when the object is no longer required. This includes all Windows controls, since they all own Windows handles! You might ask, why not put the code to release those resources in the object’s finalizer? (A finalizer is a method that the CLR runs just prior to an object’s destruction). The main reason is that the garbage collector is concerned with memory issues and not resource issues. So on a PC with a few gigabytes of free memory, the garbage collector may wait an hour or two before even getting out of bed!
So how do we get our textbox to release that Windows handle and disappear off the screen when we’re done with it? Well, first, our example was pretty artificial. In reality, we would have put the textbox control on a form in order to make it visible it in the first place. Assuming myForm was created earlier on, and is still in scope, this is what we’d typically do:
myForm.Controls.Add (myTextBox);
As well as making the control visible, this would also give it another referee (myForm.Controls). This means that when the local reference variable myTextBox drops out of scope, there’s no danger of the textbox becoming eligible for garbage collection. The other effect of adding it to the Controls collection is that the .NET framework will deterministically call a method called Dispose on all of its members the instant they’re no longer needed. And in this Dispose method, the control can release its Windows handle, as well as dropping the textbox off the screen.
All classes that implement IDisposable (including all Windows Forms controls) have a Dispose method. This method must be called when an object is no longer needed in order to release resources other than memory. There are two ways this happens:
- manually (by calling Dispose explicitly)
- automatically: by adding the object to a .NET container, such as a Form, Panel, TabPage or UserControl. The container will ensure that when it’s disposed, so are all of its members. Of course, the container itself must be disposed (or in turn, be part of another container).
In the case of Windows Forms controls, we nearly always add them to a container – and hence rely on automatic disposal.
The same thing applies to classes such as FileStream—these need to be disposed too. Fortunately, C# provides a shortcut for calling Dispose on such objects, in a robust fashion: the usingstatement:
using (Stream s = File.Create ("myfile.txt"))
{
...
}
This translates to the following code:
Stream s = File.Create ("myfile.txt");
try
{
...
}
finally
{
if (s != null) s.Dispose();
}
The finally block ensurse that Dispose still gets executed should an exception be thrown within the main code block.