Friday, March 19, 2010

String


MANIPULATING STRINGS
Strings
The String  class provide strings functionality in .NET. 
 Understanding the String Class

The String class implements the functionality of string data type. String class is defined in the System namespace. Here are few important things about the String class before we proceed:
  1. An instance of String is immutable, means once an instance is created, it cannot be modified. There are methods, which returns a new String to return a new sub string from it.
  2. Index of String is zero based. Means the first character of the index is 0th element of the String and last character of the String is total number of elements in the string - 1.
  3. By default a String is an empty string (""). So you don't have to initialize it as you used to do in C++ or other languages. An empty string is greater than the null value.
String class Members

String class provides two properties - Chars and Length. The Chars property returns the character at a specified position in a string and the Length property returns the number of characters in a string.

String class provides two types of methods - static and instance. Static methods can only be used by String class, not by an instance of the String class. The instance methods are used by instances of the String class.
Static Methods of String/string
Compare: Compares the values of two strings.

Concat: Concatenates (joins) two or more strings into one string.

Copy: Creates a new string from an existing string.

Equals :Compares two strings to determine whether they contain the same value. Returns true if the two values are equal; otherwise, returns false.

Join :Concatenates two or more strings. A specified “separator string” is placed between each of the original strings.


Methods and Properties of Each Instance

Clone: Returns a copy of the stored string.

CompareTo: Compares the value of this string with the value of another string. Returns a negative number if this string is less than the compared string, 0 if equal, and a positive number if the value of this string is greater.

CopyTo: Copies a portion of or all of a string to a new string or character array.

EndsWith: Determines whether the end of the value stored in the string is equal to a
string value. If they are equal, true is returned; otherwise, false is returned.
Equals Compares two strings to determine whether they contain the same value.
Returns true if the two values are equal; otherwise, returns false.

IndexOf: Returns the index (location) of the first match for a character or string. Returns
-1 if the value is not found.

Insert :Inserts a value into a string. This is done by returning a new string.

LastIndexOf: Returns the index (location) of the last match for a character or a string.
Returns -1 if the value is not found.

Length: Returns the length of the value stored in the string. The length is equal to the
number of characters contained.

PadLeft: Right-justifies the value of a string and then pads any remaining spaces with a
specified character (or space).

PadRight: Left-justifies the value of a string and then pads any remaining spaces with a
specified character (or space).

Remove: Deletes a specified number of characters from a specified location within a
string.

Split: The opposite of Join. Breaks a string into substrings based on a specified value. The specified value is used as a breaking point.

StartsWith: Determines whether the value stored in a string starts with a specified character
or set of characters. Returns true if there is a match and false if not. If
specified character is null, true is also returned.

Substring: Returns a substring from the original string starting at a specified location. The
number of characters for the substring might also be specified but is not required.

ToCharArray: Copies the characters in the current string value to a char array.

ToLower: Returns a copy of the current value in all lowercase letters.

ToUpper: Returns a copy of the current value in all uppercase characters.

Trim: Removes copies of a specified string from the beginning and end of the current
string.

TrimEnd: Removes copies of a specified string from the end of the current string.

TrimStart: Removes copies of a specified string from the beginning of the current string.

Comparing Strings

The Compare method compares two strings and returns an integer value. The return value of Compare method can be less than zero, greater than zero or equals to zero
 The following code compares two strings and return results on the System console.

// Comparing two strings
//====================================
string str1 = "ppp";
string str2 = "ccc";
int res = String.Compare(str1, str2);
Console.WriteLine("First result:" +res.ToString());
str2 = "ttt"; res = String.Compare(str1, str2);
Console.WriteLine("Second result:" +res.ToString());
str1 = "ttt"; res = String.Compare(str1, str2);
Console.WriteLine("Third result:" +res.ToString));
//====================================

The CompareTo method is an instance method. It compares a value (either a string or on object) with a string instance. Return values of this method are same as the Compare method. The following source code compares two strings.

// CompareTo Method
string str = "kkk";
Console.WriteLine( str.CompareTo(str1) );

Copy and Concatenating Strings

The Concat method adds strings (or objects) and returns a new string. Using Concat method, you can add two strings, two objects and one string and one object or more combinations of these two.

The following source code concatenate two strings.

string str1 = "ppp";
string str2 = "ccc";
string strRes = String.Concat(str1, str2);
Console.WriteLine(strRes);

The following source code concatenates one string and one object.

object obj = (object)12;
strRes = String.Concat(str1, obj);
Console.WriteLine(strRes);

The Copy method copies contents of a string to another. The Copy method takes a string as input and returns another string with the same contents as the input string. For example, the following code copies str1 to strRes.

string str1 = "ppp";
string str2 = "ccc";
string strRes = String.Copy(str1);
Console.WriteLine("Copy result :" + strRes);

The CopyTo method copies a specified number of characters from a specified position in this instance to a specified position in an array of characters. For example, the following example copies contents of str1 to an array of characters. You can also specify the starting character of a string and number of characters you want to copy to the array.

string str1 = "ppp";
char[] chrs = new Char[2];
str1.CopyTo(0, chrs, 0, 2);

The Clone method returns a new copy of a string in form of object. The following code creates a clone of str1.

string str1 = "ppp";
object objClone = str1.Clone();
Console.WriteLine("Clone :"+objClone.ToString());

The Join method is useful when you need to insert a separator (String) between each element of a string array, yielding a single concatenated string. For example, the following sample inserts a comma and space (", ") between each element of an array of strings.

string str1 = "ppp";
string str2 = "ccc";
string str3 = "kkk";
string[] allStr = new String[]{str1, str2, str3};
string strRes = String.Join(", ", allStr);
Console.WriteLine("Join Results: "+ strRes);

Adding, Removing and Replacing Strings

The Insert method inserts a specified string at a specified index position in an instance. For example, the following source code inserts "bbb" after second character in str1 and the result string is "pbbbpp".

string str1 = "ppp";
string strRes = str1.Insert(2, "bbb");
Console.WriteLine(strRes.ToString());

The Remove method deletes a specified number of characters from a specified position in a string. This method returns result as a string. For example, the following code removes three characters from index 3.

string s = "123abc000";
Console.WriteLine(s.Remove(3, 3));

The Replace method replaces all occurrences of a specified character in a string. For example, the following source code replaces all p character instances of str1 with character l and returns string "lll".

string str1 = "ppp";
string repStr = str1.Replace('p', 'l');
Console.WriteLine("Replaced string:"+ repStr.ToString() );

The Split method separates strings by a specified set of characters and places these strings into an array of strings. For example, the following source code splits strArray based on ',' and stores all separated strings in an array.

string str1 = "ppp";
string str2 = "ccc";
string str3 = "kkk";
string strAll3 = str1 + ", " +str2+", "+str3 ;
string[] strArray = strAll3.Split(',');
foreach (string itm in strArray)
{
Console.WriteLine(itm.ToString() );
}

Uppercase and Lowercase
The ToUpper and ToLower methods convert a string in uppercase and lowercase respectively. These methods are easy to use. The following code shows how to use ToUppler and ToLower methods.

string aStr = "adgas";
string bStr = "ABNMDWER";
string strRes = aStr.ToUpper();
Console.WriteLine("Uppercase:"+ strRes.ToString());
strRes = bStr.ToLower();
Console.WriteLine("Lowercase:"+ strRes.ToString());
Formatting Strings

You can use the Format method to create formatted strings and concatenate multiple strings representing multiple objects. The Format method automatically converts any passed object into a string.

For example, the following code uses integer, floating number and string values and format them into a string using the Format method.

Listing 1: Using Format method to format a string

int val = 7;
string name = "Mr. John";
float num = 45.06f;
string str = String.Format ("Days Left : {0}. Current DataTime: {1:u}. \n String: {2}, Float: {3}" , val, DateTime.Now, name, num);
Console.WriteLine(str);


Trimming and Removing Characters from Strings

The String class provides Trim, TrimStart and TrimEnd methods to trim strings. The Trim method removes white spaces from the beginning and end of a string. The TrimEnd method removes characters specified in an array of characters from the end of a string and TrimStart method removes characters specified in an array of characters from the beginning of a string.

You can also use the Remove method to remove characters from a string. The Listing 2 code shows how to use these methods.
String str = " C# ";
Console.WriteLine("Hello{0}World!", str);
string trStr = str.Trim();
Console.WriteLine("Hello{0}World!", trStr );
str = "Hello World!";
char[] chArr = {'e', 'H','l','o',' ' };
trStr = str.TrimStart(chArr);
Console.WriteLine(trStr);
str = "Hello World!";
char[] chArr1 = {'e', 'H','l','o',' ' };
trStr = str.TrimEnd(chArr1);
Console.WriteLine(trStr);
string MyString = "Hello Delta World!";
Console.WriteLine(MyString.Remove(5,10));

Padding Strings

The PadLeft and PadRight methods can be used to pad strings. The PadLeft method right-aligns and pads a string so that its rightmost character is the specified distance from the beginning of the string. The PadRight method left-aligns and pads a string so that its rightmost character is a specified distance from the end of the string. These methods return new String objects that can either be padded with empty spaces or with custom characters. Listign 3 shows how to use these methods.

Listing 3: Using padding methods
string str1 = "My String";
Console.WriteLine(str1.PadLeft(20, '-'));string str2 = "My String";
Console.WriteLine(str2.PadRight(20, '-'));

Monday, March 8, 2010

Enumerations



An enumeration is a special kind of value type limited to a restricted and unchangeable set of numerical values. By default, these numerical values are integers, but they can also be longs, bytes, etc. (any numerical value except char) as will be illustrated below.
When you define an enumeration you provide literals which are then used as constants for their corresponding values. The following code shows an example of such a definition:
 1.
public enum DAYS
2.
{
3.
    Monday,
4.
    Tuesday,
5.
    Wednesday,
6.
    Thursday,
7.
    Friday,
8.
    Saturday,
9.
    Sunday
10.
}

Note, however, that there are no numerical values specified in the above. Instead, the numerical values are (we think) set up according to the following two rules:
1. For the first literal: if it is unassigned, set its value to 0.
2. For any other literal: if it is unassigned, then set its value to one greater than the value of the preceding literal.
From these two rules, it can be seen that DAYS.Monday will be set to 0, and the values increased until DAYS.Sunday is set to 6. Note also how we are referring to these values - the values specified in an enumeration are static, so we have to refer to them in code using the name of the enumeration: "DAYS.Monday" rather than just "Monday". Furthermore, these values are final - you can't change their runtime value.
The following code demonstrates how you can override the default setting which makes the default values integers. In this example, the enumeration values are set to bytes.


1.
enum byteEnum : byte
2.
{
3.
    A,
4.
    B
5.
}

You can also override the default numerical values of any and all of the enumeration elements. In the following example, the first literal is set to value 1. The other literals are then set up according to the second rule given above, so DAYS.Sunday will end up equal to 7.
1.
public enum DAYS
2.
{
3.
    Monday=1,
4.
    Tuesday,
5.
    Wednesday,
6.
    Thursday,
7.
    Friday,
8.
    Saturday,
9.
    Sunday
10.
}

In the two examples given, the values of each literal has been unique within the enumeration. This is usually how you will want things to be, but in fact the values need not be unique. In the following case, the value of DAYS.Thursday is also set to equal 1. The values assigned to the other literals will follow the rules given previously, so both DAYS.Tuesday and DAYS.Friday will equal 2, etc.
1.
public enum DAYS
2.
{
3.
    Monday=1,
4.
    Tuesday,
5.
    Wednesday,
6.
    Thursday=1,
7.
    Friday,
8.
    Saturday,
9.
    Sunday
10.
}

In C# enumerations are type-safe, by which we mean that the compiler will do its best to stop you assigning illicit values to enumeration typed variables. For instance, the following code should not compile:
1.
int i = DAYS.Monday;
2.
DAYS d = i;

In order to get this code to compile, you would have to make explicit casts both ways (even converting from DAYS to int), ie:
1.
int i = (int)DAYS.Monday;
2.
DAYS d = (DAYS)i;

At this point you may be wondering what happens if you cast an int to an enumeration value where that same value is defined for two elements within the enumeration. And the answer is this: one of the elements is given 'primary' status, so it gets picked ahead of the other.
A useful feature of enumerations is that one can retrieve the literal as a string from the numeric constant with which it is associated. In fact, this is given by the default ToString() method, so the following expression comes out as true:
DAYS.Monday.ToString()=="Monday"
The following code prints out both the literal and its constant value for the specified enumeration.
1.
using System;
2.
public class EnumTest
3.
{
4.
    public enum DAYS: byte
5.
    {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}
6.
    
7.
    public static void Main()
8.
    {
9.
        Array dayArray = Enum.GetValues(typeof(EnumTest.DAYS));
10.
        foreach (DAYS day in dayArray)
11.
            Console.WriteLine("Number {1} of EnumTest.DAYS is {0}", day, day.ToString("d"));
12.
    }
13.
}

Since it's not immediately obvious what's going on in the main method here, let's take the time to go through it.
On line 9 we use the static GetValues method of the Enum class. When you pass this class an enumeration type - in this case, the type corresponding to EnumTest.DAYS - it returns an array of all the values of the elements within that enumeration. Note that the Enum class also has the GetNames method, which returns the literal strings.
On line 10 we set up a foreach loop, pulling out, into day, each value in the dayArray in turn. Note that this value is of type DAYS.
On line 11 we use string interpolation as part of the Console.WriteLine method. This method makes use of the String.Format method, so is equivalent to:
Console.WriteLine(String.Format("Number {1} of EnumTest.DAYS is {0}", day, day.ToString("d")));
And what the String.Format method does is to take 'textual representations' of the objects it is passed as parameters, and slots them into the appropriate places within the 'format string' it is passed. So this line of code is basically equivalent to:
Console.WriteLine("Number " + day.ToString("d").ToString() + " of EnumTest.DAYS is " + day.ToString());
Now, we've already noted that day.ToString() will return a literal string, but what about the method day.ToString("d")? Well, we had a stab at explaining this a while ago, but did very badly. In fact, we just made an error. So hopefully the following will be better.
The ToString method can take a single IFormatProvider parameter which indicates how the string conversion should be conducted. Values for this parameter can include things like "g", "d", "x", "f", etc. The stated implication of "d", however, is to render in 'Decimal format'. And when we use this on an enumeration member, it provides a string representation of the *numerical value* of the enumeration member. So, when we run the code above, what we get is the following output:
Number 0 of EnumTest.DAYS is Monday
Number 1 of EnumTest.DAYS is Tuesday
Number 2 of EnumTest.DAYS is Wednesday
Number 3 of EnumTest.DAYS is Thursday
Number 4 of EnumTest.DAYS is Friday
Number 5 of EnumTest.DAYS is Saturday
Number 6 of EnumTest.DAYS is Sunday

Tuesday, March 2, 2010

Properties



Another type of class member is the property. A property combines a field with the methods that access it. As some examples earlier in this book have shown, often you will want to create a field that is available to users of an object, but you want to maintain control over the operations allowed on that field. For instance, you might want to limit the range of values that can be assigned to that field. While it is possible to accomplish this goal through the use of a private variable along with methods to access its value, a property offers a better, more streamlined approach.
Properties are similar to indexers. A property consists of a name along with get and set accessors. The accessors are used to get and set the value of a variable. The key benefit of a property is that its name can be used in expressions and assignments like a normal variable, but in actuality the get and set accessors are automatically invoked. This is similar to the way that an indexer’s get and set accessors are automatically used.
The general form of a property is shown here:
type name {
    get {
        // get accessor code
    }
 
    set {
        // set accessor code
    }
}
Here, type specifies the type of the property, such as int, and name is the name of the property. Once the property has been defined, any use of name results in a call to its appropriate accessor. The set accessor automatically receives a parameter called value that contains the value being assigned to the property.
It is important to understand that properties do not define storage locations. Thus, a property manages access to a field. It does not, itself, provide that field. The field must be specified independently of the property.
Here is a simple example that defines a property called MyProp, which is used to access the field prop. In this case, the property allows only positive values to be assigned.
// A simple property example.
 
using System;
 
class SimpProp {
  int prop; // field being managed by MyProp
 
  public SimpProp() { prop = 0; }
 
  /* This is the property that supports access to
     the private instance variable prop.  It
     allows only positive values. */
  public int MyProp {
    get {
      return prop;
    }
    set {
      if(value >= 0) prop = value;
    }
  }
}
 
// Demonstrate a property.
class PropertyDemo {
  public static void Main() {
    SimpProp ob = new SimpProp();
 
    Console.WriteLine("Original value of ob.MyProp: " + ob.MyProp);
    ob.MyProp = 100; // assign value
    Console.WriteLine("Value of ob.MyProp: " + ob.MyProp);
 
    // Can't assign negative value to prop
    Console.WriteLine("Attempting to assign -10 to ob.MyProp");
    ob.MyProp = -10;
    Console.WriteLine("Value of ob.MyProp: " + ob.MyProp);
  }
}
Output from this program is shown here:
Original value of ob.MyProp: 0
Value of ob.MyProp: 100
Attempting to assign -10 to ob.MyProp
Value of ob.MyProp: 100
Let’s examine this program carefully. The program defines one private field, called prop, and a property called MyProp that manages access to prop. As explained, a property by itself does not define a storage location. A property simply manages access to a field. Thus, there is no concept of a property without an underlying field. Furthermore, because prop is private, it can be accessed only through MyProp.
The property MyProp is specified as public so that it can be accessed by code outside of its class. This makes sense because it provides access to prop, which is private. The get accessor simply returns the value of prop. The set accessor sets the value of prop if and only if that value is positive. Thus, the MyProp property controls what values prop can have. This is the essence of why properties are important.
The type of property defined by MyProp is called a read-write property because it allows its underlying field to be read and written. It is possible, however, to create read-only and write-only properties. To create a read-only property, define only a get accessor. To define a write-only property, define only a set accessor.
You can use a property to further improve the fail-soft array class. As you know, all arrays have a Length property associated with them. Up to now, the FailSoftArray class simply used a public integer field called Length for this purpose. This is not good practice, though, because it allows Length to be set to some value other than the length of the fail-soft array. (For example, a malicious programmer could intentionally corrupt its value.) We can remedy this situation by transforming Length into a read-only property, as shown in the following version of FailSoftArray:
// Add Length property to FailSoftArray.
 
using System;
 
class FailSoftArray {
  int[] a; // reference to underlying array
  int len; // length of array -- underlies Length property
 
  public bool errflag; // indicates outcome of last operation
 
  // Construct array given its size.
  public FailSoftArray(int size) {
    a = new int[size];
    len = size;
  }
 
  // Read-only Length property.
  public int Length {
    get {
      return len;
    }
  }
 
  // This is the indexer for FailSoftArray.
  public int this[int index] {
    // This is the get accessor.
    get {
      if(ok(index)) {
        errflag = false;
        return a[index];
      } else {
        errflag = true;
        return 0;
      }
    }
 
    // This is the set accessor
    set {
      if(ok(index)) {
        a[index] = value;
        errflag = false;
      }
      else errflag = true;
    }
  }
 
  // Return true if index is within bounds.
  private bool ok(int index) {
   if(index >= 0 & index < Length) return true;
   return false;
  }
}
 
// Demonstrate the improved fail-soft array.
class ImprovedFSDemo {
  public static void Main() {
    FailSoftArray fs = new FailSoftArray(5);
    int x;
 
    // can read Length
    for(int i=0; i < fs.Length; i++)
      fs[i] = i*10;
 
    for(int i=0; i < fs.Length; i++) {
      x = fs[i];
      if(x != -1) Console.Write(x + " ");
    }
    Console.WriteLine();
 
    // fs.Length = 10; // Error, illegal!
  }
}
Length is now a property that uses the private variable len for its storage. Length defines only a get accessor, which means that it is read-only. Thus, Length can be read, but not changed. To prove this to yourself, try removing the comment symbol preceding this line in the program:
// fs.Length = 10; // Error, illegal!
When you try to compile, you will receive an error message stating that Length is read-only.
Although the addition of the Length property improves FailSoftArray, it is not the only improvement that properties can make. The errflag member is also a prime candidate for conversion into a property since access to it should also be limited to read-only. Here is the final improvement of FailSafeArray. It creates a property called Error that uses the original errflag variable as its storage.
// Convert errflag into a property.
 
using System;
 
class FailSoftArray {
  int[] a; // reference to underlying array
  int len; // length of array
 
  bool errflag; // now private
 
  // Construct array given its size.
  public FailSoftArray(int size) {
    a = new int[size];
    len = size;
  }
 
  // Read-only Length property.
  public int Length {
    get {
      return len;
    }
  }
 
  // Read-only Error property.
  public bool Error {
    get {
      return errflag;
    }
  }
  // This is the indexer for FailSoftArray.
  public int this[int index] {
    // This is the get accessor.
    get {
      if(ok(index)) {
        errflag = false;
        return a[index];
      } else {
        errflag = true;
        return 0;
      }
    }
 
    // This is the set accessor
    set {
      if(ok(index)) {
        a[index] = value;
        errflag = false;
      }
      else errflag = true;
    }
  }
 
  // Return true if index is within bounds.
  private bool ok(int index) {
   if(index >= 0 & index < Length) return true;
   return false;
  }
}
 
// Demonstrate the improved fail-soft array.
class FinalFSDemo {
  public static void Main() {
    FailSoftArray fs = new FailSoftArray(5);
 
    // use Error property
    for(int i=0; i < fs.Length + 1; i++) {
      fs[i] = i*10;
      if(fs.Error)
        Console.WriteLine("Error with index " + i);
    }
 
  }
}
The creation of the Error property has caused two changes to be made to FailSoftArray. First, errflag has been made private because it is now used as the underlying storage for the Error property. Thus, it won’t be available directly. Second, the read-only Error property has been added. Now, programs that need to detect errors will interrogate Error. This is demonstrated in Main( ), where a boundary error is intentionally generated, and the Error property is used to detect it.

Property Restrictions

Properties have some important restrictions. First, because a property does not define a storage location, it cannot be passed as a ref or out parameter to a method. Second, you cannot overload a property. (You can have two different properties that both access the same variable, but this would be unusual.) Finally, a property should not alter the state of the underlying variable when the get accessor is called. Although this rule is not enforced by the compiler, violating it is wrong. A get operation should be nonintrusive.

Using Access Modifiers with Accessors

Beginning with C# 2.0, you can specify an access modifier, such as private, when declaring a get or set accessor. Doing so enables you to control access to an accessor. For example, you might want to make set private to prevent the value of a property or an indexer from being set by code outside its class. In this case, the property or indexer could be read by any code, but set only by a member of its class.
Here is an example:
// Use an access modifier with an accessor.
 
using System;
 
class PropAccess {
  int prop; // field being managed by MyProp
 
  public PropAccess() { prop = 0; }
 
  /* This is the property that supports access to
     the private instance variable prop.  It allows
     any code to obtain the value of prop, but
     only other class members can set the value
     of prop. */
  public int MyProp {
    get {
      return prop;
    }
    private set { // now, private
      prop = value;
    }
  }
 
  // This class member increments the value of MyProp.
  public void incrProp() {
    MyProp++; // OK, in same class.
  }
}
 
// Demonstrate accessor access modifier.
class PropAccessDemo {
  public static void Main() {
    PropAccess ob = new PropAccess();
 
    Console.WriteLine("Original value of ob.MyProp: " + ob.MyProp);
//    ob.MyProp = 100; // can't access set
 
    ob.incrProp();
    Console.WriteLine("Value of ob.MyProp after increment: "
                      + ob.MyProp);
  }
}
In the PropAccess class, the set accessor is specified private. This means that it can be accessed by other class members, such as incrProp( ), but cannot be accessed by code outside of PropAccess. This is why the attempt to assign ob.MyProp a value inside PropAccessDemo is commented out.
Here are some restrictions that apply to using access modifiers with accessors. First, only the set or the get accessor can be modified, not both. Furthermore, the access modifier must be more restrictive than the access level of the property or indexer.