Monday, July 16, 2012

Good to know in .net


  1. Char in c# provides some useful static functions to do some common checking functions such as
Console.WriteLine(char.IsUpper('U')); //returns true
      
Console.WriteLine(char.IsNumber('1'));//returns true
      
Console.WriteLine(char.IsDigit('1'));//returns true
      
Console.WriteLine(char.IsLower('u'));//returns true
      
Console.WriteLine(char.IsLetterOrDigit('A'));//returns true
      
Console.WriteLine(char.IsLetterOrDigit('1'));//returns true
      
Console.WriteLine(char.IsWhiteSpace(' '));//returns true

  1. If you have created a function before which takes out and ref parameters then you probably already know this.
    1. Function that takes out parameters needs to assign a value to the parameter before leaving the control. While it is not the case with ref.
    2. When you pass a variable to a function that takes ref parameter you explicitly need to assign a value before passing it to the function. While it is not the case with out.
  2. Enum
    1. By default the underlying storage type for the values in enum are int. You can change this type to any of the type(byte, sbyte, short, ushort, int, uint, long, or ulong). This can be particularly helpful in saving some extra space by deriving from byte instead of int.

public enum MyEnum:byte
   {
       EnumType1=100,
       EnumType2=255 //maximum limit for the byte.
   }

Plus you definitely need to take care of the limit imposed by the type when you are deriving from the type.
  1. To find out the underlying storage type of the enum you can use the Enum.GetUnderlyingType() function.

var ee = MyEnum.EnumType1;Console.WriteLine(Enum.GetUnderlyingType(ee.GetType()));


  1. The number of members that can be declared in an enum type is really dependent on the underlying storage type of the enum. So in above case the MyEnum can have 256 members, but if the underlying type wasn’t changed then it would have been 2^32(the default type is int whose size is 4 byte).

  1. default keyword in c# can be used to return default value of a generic parameter type. Default in a sense, it returns null for reference type and 0 for numeric type. This can be particulary useful when creating a generic function and need to initialize a new variable with the default value of the generic parameter type, coz a generic function may not necessarily know the type of parameter type being passed.
public static T GenericFunction<T>()
       {
           return default(T);
       }


  1. Under the hood c# properties are compiled into hidden methods with get_ and set_ prefixes appended. Your getter property will be appended with get_ and setter property will be appended with set_ prefixes.
  2. Same is the case with events. Events are prefixed with add_ and remove_ prefixes.
  3. Struct cannot inherit. They are always sealed.
  4. Type Conversion:

  • Implicit conversion automatically happens when you try to assign a smaller/derived data type into a larger/base data type which can accommodate without any loss of data.
For e.g
int i=100;
long j=i;//implicit conversion

  • Explicit conversion happens when you cast from one data type to other using cast operators explicitly. When you want to store the larger/base data type to smaller/derived data type you need to explicitly casting.
For e.g
long j=100;
int i=(int)j;

  • Inheritance model of c# automatically allows you to implicitely cast derived class to base class, however you can only explicitely cast base class to derived class using cast operator. But it is converted to derived class only when the base class has been assigned the same derived class previously.
For eg.
public class TCBase
    {
        public string Param1 { get; set; }
       
    }

    public class  
TCDerived:TCBase
    {
        public string Param2 { get; set; }

    }

   public class
TCDerived2 : TCBase
   {
       public string Param2 { get; set; }

   }

//this is valid
           
TCDerived derived=new TCDerived();
           
TCBase base1 = derived;
           
TCDerived derived2 = base1 as TCDerived;
//this is valid but won't cast
           
           
TCBase base2 = new TCBase();
           
TCDerived derived3 = base2 as TCDerived;


  • To be able to cast one type to other you can either provide implicit operator or explicit. If you have provided implicit operator then explicit casting works automatically.
For e.g
public class  TCDerived:TCBase
    {
        public string Param2 { get; set; }

        public static explicit operator
TCDerived(TCDerived2 d2)
        {
            return new
TCDerived() { Param2 = d2.Param2, Param1 = d2.Param1 };
        }
    }

    //this is valid
           
TCDerived2 d2 =new TCDerived2();
           
TCDerived d = d2;

           //this is not valid since we haven't provided implicit or explicit conversion operator
           
TCDerived dd = new TCDerived();
           
TCDerived2 dd2 = dd;



  1. Partial Method.
Partial class has been around since c# 2.0 but partial method has been available from c#3.0. This feature is not something that many know or use quite often. Even microsoft doesn't seem to brag about this feature, that's why many of us are still unaware about it. Let’s check out a small sample.
public partial class PartialMethodClass
   {

       public void Test()
       {
           
Console.WriteLine("from test method");
           PartialMethod();
           //some other stuff
       }

       partial void PartialMethod();

   }

If you compile your assembly without implementing this PartialMethod() then c# compiler completely strips out the call to this method. In above case the the line calling PartialMethod() method in Test() method will be stripped out by the compiler in compiled assembly.
You can implement this method in another part of the partial class as
public partial class PartialMethodClass
   {
       partial void PartialMethod()
       {
           
Console.WriteLine("from partial method");
       }
   }

Some important things to remember about partial method.

  • Partial methods can only be defined within a partial class.
  • Partial methods must return void.
  • Partial methods can be static or instance level.
  • Partial methods can have arguments (including parameters modified by this, ref, or params—but not with the out modifier).
  • Partial methods are always implicitly private.


  1. Anonymous Type.

  • .net compiler always creates anonymous class for anonymous types.
  • When you test the equality of two classes the “==” operator always checks for their references. Similarly the equals method, by default does the same unless you override the method and provide your own logic. However the equals method of anonymous type compares each property rather than their references.
  • If two anonymous types have same class signature .net compiler creates only 1 anonymous class for both of them.
  • You don’t control the name of the anonymous type.
  • Anonymous types always extend System.Object.
  • The fields and properties of an anonymous type are always read-only.
  • Anonymous types cannot support events, custom methods, custom operators, or custom overrides.
  • Anonymous types are always implicitly sealed.
  • Anonymous types are always created using the default constructor


  1. Linq
    1. The Linq methods such as where,skip,select,reverse are all extension methods defined for generic IEnumerable<> type. So all container/collection types derived from this interface automatically gets linq enabled.
    2. Other container types such as ArrayList which derives from non-generic IEnumerable interface doesn’t get linq extension methods. However .net provides another generic extension method called OfType<> defined in Enumerable class for non-generic IEnumerable interface which converts the source to generic IEnumerable<> of type supplied in type parameter. For e.g
ArrayList arlist=new ArrayList();
           //this is not valid.
           //arlist.where();
           //this is valid
           arlist.OfType<string>().Where(m=>m.Equals(
"something"));


  1. A .NET version number is composed of the four parts (<major>.<minor>.<build>.<revision>).
  2. Up to .net 3.5 assemblies in GAC resides under assembly folder of %windir%. From 4.0 assemblies in GAC resides under \Microsoft.NET\assembly\GAC_MSIL of %windir%. Under this new folder, you will find a set of subdirectories, each of which is named identically to the friendly name of a particular code library (for example, System.Windows.Forms, \System.Core, and so on). Beneath a given friendly name folder, you’ll find yet another subdirectory that always takes the following naming convention: v4.0_major.minor.build.revision__publicKeyTokenValue


  1. Probing:
    1. By default when an application loads, the CLR searches for dependent assemblies in the application folder and if not found in case of public/shared assembly, it doesn an extra search in assembly GAC. Probing is a way to tell CLR that the dependent assemblies can be found within the subdirectories of the current directory.
    2. Multiple subdirectories can be assigned by separating the path by colon.
    3. Absolute path cannot be specified.
    4. relative path outside the client’s application directory cannot be specified.
    5. CLR will load the very first assembly it finds during the probing process.
For e.g
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="MyLibrariyFolder"/>
</assemblyBinding>
</runtime>
</configuration>


  1. CodeBase:
<codeBase> is another way of probing dependent assemblies from absolute paths.
If the value assigned to a <codeBase> element is located on a remote machine, the assembly will be downloaded on demand to a specific directory in the GAC termed the download cache
To probe the assemblies without strong name, the dependent assembly needs to be relative to the client’s application directory.

  1. Redirecting shared assembly to different version
One thing to note in .net is, a machine can have the same shared assembly with different versions. So if your application has referenced version 1.0.0.0 of some assembly but if the production environment has higher version of the assembly insted then you will run into problem. Now either you need to change the reference and recompile and re-deploy your application or you can change the binding redirect configuration of your application and direct the CLR to try to load the new version instead.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="ReferencedLibrary"
publicKeyToken="22ABCD294331EFGHI"
culture=""/>
<bindingRedirect oldVersion= "1.0.0.0" newVersion= "2.0.0.0"/>
</dependentAssembly>

</assemblyBinding>
</runtime>
</configuration>

Now assume you are the developer of “ReferencedLibrary” and after few days of publishing your assembly(version 1.0.0.0) to your clients you discovered few major bugs that need to be fixed but decided to give it a new version number(2.0.0.0). But here is the problem. The server of your client has mulitple applications that reference your library and if you were to follow the above method, the admin might have to open each application’s configuration files and add the above configuration section to redirect the assembly. It’s not something the admin would wanna do. To overcome this issue, you could as a developer of “ReferencedLibrary” create a publisher policy file and supply the publisher assembly along with your new versioned assembly. So when CLR detects the publisher file in GAC it reads the binding redirect configuration and tries to load the new version(2.0.0.0) instead of the older one(1.0.0.0). For more please refer to http://msdn.microsoft.com/en-us/library/dz32563a(v=vs.71).aspx.


  1. Self Executing anonymous function(source: http://blog.dmbcllc.com/self-executing-anonymous-function)
  2. ((Func<int>)(delegate()
    {
       return 0;
    }))();

  3. AppSettingsReader:
This is something I’ve never heard or used it before. AppSettingsReader is a simple yet useful class in System.Configuration that can read the <appSettings> section from application configuration file.
Usage:
AppSettingsReader appSettingsReader=new AppSettingsReader();
      var appkey1Value= appSettingsReader.GetValue(
"appkey1", typeof (string));

If the key is not found it throws InvalidOperationException.



References:

No comments:

Post a Comment