Showing posts with label C# Advanced. Show all posts
Showing posts with label C# Advanced. Show all posts

Monday, June 1, 2015

1. C# - Attributes

Csharp Tutorial 

An attribute is a declarative tag that is used to convey information to runtime about the behaviors of various elements like classes, methods, structures, enumerators, assemblies etc. in your program. You can add declarative information to a program by using an attribute. A declarative tag is depicted by square ([ ]) brackets placed above the element it is used for.
Attributes are used for adding metadata, such as compiler instruction and other information such as comments, description, methods and classes to a program. The .Net Framework provides two types of attributes: the pre-defined attributes and custom built attributes.

Specifying an Attribute

Syntax for specifying an attribute is as follows:
[attribute(positional_parameters, name_parameter = value, ...)]
element
Name of the attribute and its values are specified within the square brackets, before the element to which the attribute is applied. Positional parameters specify the essential information and the name parameters specify the optional information.

Predefined Attributes

The .Net Framework provides three pre-defined attributes:
  • AttributeUsage
  • Conditional
  • Obsolete

AttributeUsage

The pre-defined attribute AttributeUsage describes how a custom attribute class can be used. It specifies the types of items to which the attribute can be applied.
Syntax for specifying this attribute is as follows:
[AttributeUsage(
   validon,
   AllowMultiple=allowmultiple,
   Inherited=inherited
)]
Where,
  • The parameter validon specifies the language elements on which the attribute can be placed. It is a combination of the value of an enumerator AttributeTargets. The default value is AttributeTargets.All.
  • The parameter allowmultiple (optional) provides value for the AllowMultiple property of this attribute, a Boolean value. If this is true, the attribute is multiuse. The default is false (single-use).
  • The parameter inherited (optional) provides value for the Inherited property of this attribute, a Boolean value. If it is true, the attribute is inherited by derived classes. The default value is false (not inherited).
For example,
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Feild |
AttributeTargets.Method |
AttributeTargets.Property, 
AllowMultiple = true)]

Conditional

This predefined attribute marks a conditional method whose execution depends on a specified preprocessing identifier.
It causes conditional compilation of method calls, depending on the specified value such as Debug or Trace. For example, it displays the values of the variables while debugging a code.
Syntax for specifying this attribute is as follows:
[Conditional(
   conditionalSymbol
)]
For example,
[Conditional("DEBUG")]
The following example demonstrates the attribute:
#define DEBUG
using System;
using System.Diagnostics;

public class Myclass
{
   [Conditional("DEBUG")]
   public static void Message(string msg)
   {
      Console.WriteLine(msg);
   }
}

class Test
{
   static void function1()
   {
      Myclass.Message("In Function 1.");
      function2();
   }
   static void function2()
   {
      Myclass.Message("In Function 2.");
   }
   
   public static void Main()
   {
      Myclass.Message("In Main function.");
      function1();
      Console.ReadKey();
   }
}
When the above code is compiled and executed, it produces the following result:
In Main function
In Function 1
In Function 2

Obsolete

This predefined attribute marks a program entity that should not be used. It enables you to inform the compiler to discard a particular target element. For example, when a new method is being used in a class and if you still want to retain the old method in the class, you may mark it as obsolete by displaying a message the new method should be used, instead of the old method.
Syntax for specifying this attribute is as follows:
[Obsolete(
   message
)]
[Obsolete(
   message,
   iserror
)]
Where,
  • The parameter message, is a string describing the reason why the item is obsolete and what to use instead.
  • The parameter iserror, is a Boolean value. If its value is true, the compiler should treat the use of the item as an error. Default value is false (compiler generates a warning).
The following program demonstrates this:
using System;

public class MyClass
{
   [Obsolete("Don't use OldMethod, use NewMethod instead", true)]
   static void OldMethod()
   {
      Console.WriteLine("It is the old method");
   }
   static void NewMethod()
   {
      Console.WriteLine("It is the new method"); 
   }
   public static void Main()
   {
      OldMethod();
   }
}
When you try to compile the program, the compiler gives an error message stating:
 Don't use OldMethod, use NewMethod instead

Creating Custom Attributes

The .Net Framework allows creation of custom attributes that can be used to store declarative information and can be retrieved at run-time. This information can be related to any target element depending upon the design criteria and application need.
Creating and using custom attributes involve four steps:
  • Declaring a custom attribute
  • Constructing the custom attribute
  • Apply the custom attribute on a target program element
  • Accessing Attributes Through Reflection
The Last step involves writing a simple program to read through the metadata to find various notations. Metadata is data about data or information used for describing other data. This program should use reflections for accessing attributes at runtime. This we will discuss in the next chapter.

Declaring a Custom Attribute

A new custom attribute should is derived from the System.Attribute class. For example,
//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]

public class DeBugInfo : System.Attribute
In the preceding code, we have declared a custom attribute named DeBugInfo.

Constructing the Custom Attribute

Let us construct a custom attribute named DeBugInfo, which stores the information obtained by debugging any program. Let it store the following information:
  • The code number for the bug
  • Name of the developer who identified the bug
  • Date of last review of the code
  • A string message for storing the developer's remarks
The DeBugInfo class has three private properties for storing the first three information and a public property for storing the message. Hence the bug number, developer's name, and date of review are the positional parameters of the DeBugInfo class and the message is an optional or named parameter.
Each attribute must have at least one constructor. The positional parameters should be passed through the constructor. The following code shows the DeBugInfo class:
//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]

public class DeBugInfo : System.Attribute
{
   private int bugNo;
   private string developer;
   private string lastReview;
   public string message;
   
   public DeBugInfo(int bg, string dev, string d)
   {
      this.bugNo = bg;
      this.developer = dev;
      this.lastReview = d;
   }
   
   public int BugNo
   {
      get
      {
         return bugNo;
      }
   }
   
   public string Developer
   {
      get
      {
         return developer;
      }
   }
   
   public string LastReview
   {
      get
      {
         return lastReview;
      }
   }
   
   public string Message
   {
      get
      {
         return message;
      }
      set
      {
         message = value;
      }
   }
}

Applying the Custom Attribute

The attribute is applied by placing it immediately before its target:
[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle
{
   //member variables
   protected double length;
   protected double width;
   public Rectangle(double l, double w)
   {
      length = l;
      width = w;
   }
   [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
   
   public double GetArea()
   {
      return length * width;
   }
   [DeBugInfo(56, "Zara Ali", "19/10/2012")]
   
   public void Display()
   {
      Console.WriteLine("Length: {0}", length);
      Console.WriteLine("Width: {0}", width);
      Console.WriteLine("Area: {0}", GetArea());
   }
}

2. C# - Reflection

Csharp Tutorial 

Reflection objects are used for obtaining type information at runtime. The classes that give access to the metadata of a running program are in the System.Reflection namespace.
The System.Reflection namespace contains classes that allow you to obtain information about the application and to dynamically add types, values, and objects to the application.

Applications of Reflection

Reflection has the following applications:
  • It allows view attribute information at runtime.
  • It allows examining various types in an assembly and instantiate these types.
  • It allows late binding to methods and properties
  • It allows creating new types at runtime and then performs some tasks using those types.

Viewing Metadata

We have mentioned in the preceding chapter that using reflection you can view the attribute information.
The MemberInfo object of the System.Reflection class needs to be initialized for discovering the attributes associated with a class. To do this, you define an object of the target class, as:
System.Reflection.MemberInfo info = typeof(MyClass);
The following program demonstrates this:
using System;

[AttributeUsage(AttributeTargets.All)]
public class HelpAttribute : System.Attribute
{
   public readonly string Url;
   
   public string Topic   // Topic is a named parameter
   {
      get
      {
         return topic;
      }
      set
      {
         topic = value;
      }
   }
   
   public HelpAttribute(string url)   // url is a positional parameter
   {
      this.Url = url;
   }
   private string topic;
}

[HelpAttribute("Information on the class MyClass")]
class MyClass
{
}
namespace AttributeAppl
{
   class Program
   {
      static void Main(string[] args)
      {
         System.Reflection.MemberInfo info = typeof(MyClass);
         object[] attributes = info.GetCustomAttributes(true);
         for (int i = 0; i < attributes.Length; i++)
         {
            System.Console.WriteLine(attributes[i]);
         }
         
         Console.ReadKey();
      }
   }
}
When it is compiled and run, it displays the name of the custom attributes attached to the class MyClass:
HelpAttribute

Example

In this example, we use the DeBugInfo attribute created in the previous chapter and use reflection to read metadata in the Rectangle class.
using System;
using System.Reflection;

namespace BugFixApplication
{
   //a custom attribute BugFix to be
   //assigned to a class and its members
   [AttributeUsage(AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]

   public class DeBugInfo : System.Attribute
   {
      private int bugNo;
      private string developer;
      private string lastReview;
      public string message;
      
      public DeBugInfo(int bg, string dev, string d)
      {
         this.bugNo = bg;
         this.developer = dev;
         this.lastReview = d;
      }
      
      public int BugNo
      {
         get
         {
            return bugNo;
         }
      }
      
      public string Developer
      {
         get
         {
            return developer;
         }
      }
      
      public string LastReview
      {
         get
         {
            return lastReview;
         }
      }
      
      public string Message
      {
         get
         {
            return message;
         }
         set
         {
            message = value;
         }
      }
   }
   [DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
   [DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
   
   class Rectangle
   {
      //member variables
      protected double length;
      protected double width;
      public Rectangle(double l, double w)
      {
         length = l;
         width = w;
      }
      [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
      public double GetArea()
      {
         return length * width;
      }
      [DeBugInfo(56, "Zara Ali", "19/10/2012")]
      public void Display()
      {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle
   
   class ExecuteRectangle
   {
      static void Main(string[] args)
      {
         Rectangle r = new Rectangle(4.5, 7.5);
         r.Display();
         Type type = typeof(Rectangle);
         
         //iterating through the attribtues of the Rectangle class
         foreach (Object attributes in type.GetCustomAttributes(false))
         {
            DeBugInfo dbi = (DeBugInfo)attributes;
            if (null != dbi)
            {
               Console.WriteLine("Bug no: {0}", dbi.BugNo);
               Console.WriteLine("Developer: {0}", dbi.Developer);
               Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
               Console.WriteLine("Remarks: {0}", dbi.Message);
            }
         }
         
         //iterating through the method attribtues
         foreach (MethodInfo m in type.GetMethods())
         {
            foreach (Attribute a in m.GetCustomAttributes(true))
            {
               DeBugInfo dbi = (DeBugInfo)a;
               if (null != dbi)
               {
                  Console.WriteLine("Bug no: {0}, for Method: {1}", dbi.BugNo, m.Name);
                  Console.WriteLine("Developer: {0}", dbi.Developer);
                  Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
                  Console.WriteLine("Remarks: {0}", dbi.Message);
               }
            }
         }
         
         Console.ReadLine();
      }
   }
}
When the above code is compiled and executed, it produces the following result:
Length: 4.5
Width: 7.5
Area: 33.75
Bug No: 49
Developer: Nuha Ali
Last Reviewed: 10/10/2012
Remarks: Unused variable
Bug No: 45
Developer: Zara Ali
Last Reviewed: 12/8/2012
Remarks: Return type mismatch
Bug No: 55, for Method: GetArea
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks: Return type mismatch
Bug No: 56, for Method: Display
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks: 

4. C# - Indexers

Csharp Tutorial 

An indexer allows an object to be indexed such as an array. When you define an indexer for a class, this class behaves similar to a virtual array. You can then access the instance of this class using the array access operator ([ ]).

Syntax

A one dimensional indexer has the following syntax:
element-type this[int index]
{
   // The get accessor.
   get
   {
      // return the value specified by index
   }
   
   // The set accessor.
   set
   {
      // set the value specified by index
   }
}

Use of Indexers

Declaration of behavior of an indexer is to some extent similar to a property. similar to the properties, you use get and set accessors for defining an indexer. However, properties return or set a specific data member, whereas indexers returns or sets a particular value from the object instance. In other words, it breaks the instance data into smaller parts and indexes each part, gets or sets each part.
Defining a property involves providing a property name. Indexers are not defined with names, but with the this keyword, which refers to the object instance. The following example demonstrates the concept:
using System;
namespace IndexerApplication
{
   class IndexedNames
   {
      private string[] namelist = new string[size];
      static public int size = 10;
      public IndexedNames()
      {
         for (int i = 0; i < size; i++)
         namelist[i] = "N. A.";
      }
      
      public string this[int index]
      {
         get
         {
            string tmp;
         
            if( index >= 0 && index <= size-1 )
            {
               tmp = namelist[index];
            }
            else
            {
               tmp = "";
            }
            
            return ( tmp );
         }
         set
         {
            if( index >= 0 && index <= size-1 )
            {
               namelist[index] = value;
            }
         }
      }
      
      static void Main(string[] args)
      {
         IndexedNames names = new IndexedNames();
         names[0] = "Zara";
         names[1] = "Riz";
         names[2] = "Nuha";
         names[3] = "Asif";
         names[4] = "Davinder";
         names[5] = "Sunil";
         names[6] = "Rubic";
         for ( int i = 0; i < IndexedNames.size; i++ )
         {
            Console.WriteLine(names[i]);
         }
         
         Console.ReadKey();
      }
   }
}
When the above code is compiled and executed, it produces the following result:
Zara
Riz
Nuha
Asif
Davinder
Sunil
Rubic
N. A.
N. A.
N. A.

Overloaded Indexers

Indexers can be overloaded. Indexers can also be declared with multiple parameters and each parameter may be a different type. It is not necessary that the indexes have to be integers. C# allows indexes to be of other types, for example, a string.
The following example demonstrates overloaded indexers:
using System;
namespace IndexerApplication
{
   class IndexedNames
   {
      private string[] namelist = new string[size];
      static public int size = 10;
      public IndexedNames()
      {
         for (int i = 0; i < size; i++)
         {
            namelist[i] = "N. A.";
         }
      }
      
      public string this[int index]
      {
         get
         {
            string tmp;
            
            if( index >= 0 && index <= size-1 )
            {
               tmp = namelist[index];
            }
            else
            {
               tmp = "";
            }
            
            return ( tmp );
         }
         set
         {
            if( index >= 0 && index <= size-1 )
            {
               namelist[index] = value;
            }
         }
      }
      public int this[string name]
      {
         get
         {
            int index = 0;
            while(index < size)
            {
               if (namelist[index] == name)
               {
                return index;
               }
               index++;
            }
            return index;
         }

      }

      static void Main(string[] args)
      {
         IndexedNames names = new IndexedNames();
         names[0] = "Zara";
         names[1] = "Riz";
         names[2] = "Nuha";
         names[3] = "Asif";
         names[4] = "Davinder";
         names[5] = "Sunil";
         names[6] = "Rubic";
         
         //using the first indexer with int parameter
         for (int i = 0; i < IndexedNames.size; i++)
         {
            Console.WriteLine(names[i]);
         }
         
         //using the second indexer with the string parameter
         Console.WriteLine(names["Nuha"]);
         Console.ReadKey();
      }
   }
}
When the above code is compiled and executed, it produces the following result:
Zara
Riz
Nuha
Asif
Davinder
Sunil
Rubic
N. A.
N. A.
N. A.
2

5. C# - Delegates

Csharp Tutorial 

C# delegates are similar to pointers to functions, in C or C++. A delegate is a reference type variable that holds the reference to a method. The reference can be changed at runtime.
Delegates are especially used for implementing events and the call-back methods. All delegates are implicitly derived from the System.Delegate class.

Declaring Delegates

Delegate declaration determines the methods that can be referenced by the delegate. A delegate can refer to a method, which has the same signature as that of the delegate.
For example, consider a delegate:
public delegate int MyDelegate (string s);
The preceding delegate can be used to reference any method that has a single string parameter and returns an int type variable.
Syntax for delegate declaration is:
delegate <return type> <delegate-name> <parameter list>

Instantiating Delegates

Once a delegate type is declared, a delegate object must be created with the new keyword and be associated with a particular method. When creating a delegate, the argument passed to the new expression is written similar to a method call, but without the arguments to the method. For example:
public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);
Following example demonstrates declaration, instantiation, and use of a delegate that can be used to reference methods that take an integer parameter and returns an integer value.
using System;

delegate int NumberChanger(int n);
namespace DelegateAppl
{
   class TestDelegate
   {
      static int num = 10;
      public static int AddNum(int p)
      {
         num += p;
         return num;
      }

      public static int MultNum(int q)
      {
         num *= q;
         return num;
      }
      public static int getNum()
      {
         return num;
      }

      static void Main(string[] args)
      {
         //create delegate instances
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         
         //calling the methods using the delegate objects
         nc1(25);
         Console.WriteLine("Value of Num: {0}", getNum());
         nc2(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}
When the above code is compiled and executed, it produces the following result:
Value of Num: 35
Value of Num: 175

Multicasting of a Delegate

Delegate objects can be composed using the "+" operator. A composed delegate calls the two delegates it was composed from. Only delegates of the same type can be composed. The "-" operator can be used to remove a component delegate from a composed delegate.
Using this property of delegates you can create an invocation list of methods that will be called when a delegate is invoked. This is called multicasting of a delegate. The following program demonstrates multicasting of a delegate:
using System;

delegate int NumberChanger(int n);
namespace DelegateAppl
{
   class TestDelegate
   {
      static int num = 10;
      public static int AddNum(int p)
      {
         num += p;
         return num;
      }

      public static int MultNum(int q)
      {
         num *= q;
         return num;
      }
      
      public static int getNum()
      {
         return num;
      }

      static void Main(string[] args)
      {
         //create delegate instances
         NumberChanger nc;
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         nc = nc1;
         nc += nc2;
         
         //calling multicast
         nc(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}
When the above code is compiled and executed, it produces the following result:
Value of Num: 75

Using Delegates

The following example demonstrates the use of delegate. The delegate printString can be used to reference method that takes a string as input and returns nothing.
We use this delegate to call two methods, the first prints the string to the console, and the second one prints it to a file:
using System;
using System.IO;

namespace DelegateAppl
{
   class PrintString
   {
      static FileStream fs;
      static StreamWriter sw;
      
      // delegate declaration
      public delegate void printString(string s);

      // this method prints to the console
      public static void WriteToScreen(string str)
      {
         Console.WriteLine("The String is: {0}", str);
      }
      
      //this method prints to a file
      public static void WriteToFile(string s)
      {
         fs = new FileStream("c:\\message.txt",
         FileMode.Append, FileAccess.Write);
         sw = new StreamWriter(fs);
         sw.WriteLine(s);
         sw.Flush();
         sw.Close();
         fs.Close();
      }
      
      // this method takes the delegate as parameter and uses it to
      // call the methods as required
      public static void sendString(printString ps)
      {
         ps("Hello World");
      }
      static void Main(string[] args)
      {
         printString ps1 = new printString(WriteToScreen);
         printString ps2 = new printString(WriteToFile);
         sendString(ps1);
         sendString(ps2);
         Console.ReadKey();
      }
   }
}
When the above code is compiled and executed, it produces the following result:
The String is: Hello World

 
Designed by Kakada Akkarak Surakkiat
Technology: របៀប​ដំឡើង Windows 10 នៅ​លើ​កុំព្យូទ័រ!: អ្នកត្រូវដឹងឲ្យ ច្បាស់ពី Windows ដែលអ្នកយក ទៅដំឡើង ដោយសារមាន Windows ខ្លះមានការ crack រួច ឬខ្លះត្រូវការ Product key ភ្លាម និងខ្លះទៀត អាចត្រូវ skip កន្លែងវាយលេខ Product key បាន តែត្រូវ Activate តាមក្រោយ ទើបប្រើប្រាស់បាន។ Technology: ដំណោះ​ស្រាយ Error 80240020 នៅ​ពេល​តម្លើង Windows 10 Free តាម​រយៈ​ការ Upgrade : មាន បញ្ហាមួយចំនួន ទាក់ទងនឹង ការតម្លើង Windows 10 នេះផងដែរ ប៉ុន្តែបញ្ហានោះ កើតឡើង ទៅលើតែកុំព្យូទ័រ មួយចំនួនប៉ុណ្ណោះ គឺខណៈពេល ដែលអ្នក ប្រើប្រាស់ បានទាញយក Windows 10 ចប់ហើយ វាបាន បង្ហាញនូវ ផ្ទាំង error មួយ ដែលមានលេខ សំគាល់ error នោះគឺ 80240020។ ដូចនេះដើម្បី ដោះស្រាយ នូវបញ្ហា មួយនេះ សូមលោកអ្នក តាមដានអាន ជាមួយយើងខ្ញុំ ទាំងអស់គ្នា !!