There are two types of objects in C#: Value types and reference types. Value types are all primitive datatypes like int and double as well as all structs (!). Reference types are all classes.
Reference types are always passed by reference, while valuetypes are always passed by value. Calling a new operator and therefore constructor on a reference type creates a new object initialized by it's contructor. Calling new on a valuetype creates no new object. It just calls the contructor on the already existing object.
Example:
PHP Code:
using System;
using System.Collections;
using System.Drawing;
namespace CProgTestCSharp
{
class Test
{
[STAThread]
static void Main(string[] args)
{
}
public void ReferenceType( Hashtable h )
{
// work with a reference ( ex-pointer )
// to a hastable. take care, maybe null
if( h == null ) return;
h.Add( "myKey", "myValue" );
}
public Point ValueType( Point p )
{
// work with a valuetype.
// Point is a struct, therefore
// never null. Changes on p have no
// effect on the parameter that
// was passed
p.X = 7;
p.Y = 5;
return p;
}
}
}
And right from the MSDN Help:
Example 1
The following example uses pointers to copy an array of bytes from src to dst.
Compile the example with the /unsafe option.
PHP Code:
// fastcopy.cs
// compile with: /unsafe
using System;
class Test
{
// The unsafe keyword allows pointers to be used within
// the following method:
static unsafe void Copy(byte[] src, int srcIndex,
byte[] dst, int dstIndex, int count)
{
if (src == null || srcIndex < 0 ||
dst == null || dstIndex < 0 || count < 0)
{
throw new ArgumentException();
}
int srcLen = src.Length;
int dstLen = dst.Length;
if (srcLen - srcIndex < count ||
dstLen - dstIndex < count)
{
throw new ArgumentException();
}
// The following fixed statement pins the location of
// the src and dst objects in memory so that they will
// not be moved by garbage collection.
fixed (byte* pSrc = src, pDst = dst)
{
byte* ps = pSrc;
byte* pd = pDst;
// Loop over the count in blocks of 4 bytes, copying an
// integer (4 bytes) at a time:
for (int n = count >> 2; n != 0; n--)
{
*((int*)pd) = *((int*)ps);
pd += 4;
ps += 4;
}
// Complete the copy by moving any bytes that weren't
// moved in blocks of 4:
for (count &= 3; count != 0; count--)
{
*pd = *ps;
pd++;
ps++;
}
}
}
static void Main(string[] args)
{
byte[] a = new byte[100];
byte[] b = new byte[100];
for(int i=0; i<100; ++i)
a[i] = (byte)i;
Copy(a, 0, b, 0, 100);
Console.WriteLine("The first 10 elements are:");
for(int i=0; i<10; ++i)
Console.Write(b[i] + "{0}", i < 9 ? " " : "");
Console.WriteLine("\n");
}
}
Example Output
The first 10 elements are:
0 1 2 3 4 5 6 7 8 9
Code Discussion
Notice the use of the unsafe keyword, which allows pointers to be used within the Copy method.
The fixed statement is used to declare pointers to the source and destination arrays. It pins the location of the src and dst objects in memory so that they will not be moved by garbage collection. The objects will be unpinned when the fixed block completes
The reason why unsafe code is beneficial here is that it allows copying the array in chunks of 4 bytes at a time, and directly by incrementing pointers, thereby getting rid of array bounds checks and address calculations in each iteration.
Hope that satisfies your hunger for code