Differentiate between a Stack and a Heap in .Net


Stack

The stack is a block of memory for storing local variables and parameters. The stack logically grows and shrinks as a function is entered and exited. Consider the following method:

static int Factorial (int x)
{
  if (x == 0)
  {
    return 1;
  }
  else
  {
    return x * Factorial (x-1);
  }
}

This method is recursive, meaning that it calls itself. Each time the method is entered, a new int is allocated on the stack, and each time the method exits, the int is deallocated.

Heap

The heap is a block of memory in which objects (i.e., reference-type instances) reside. Whenever a new object is created, it is allocated on the heap, and a reference to that object is returned. During a program’s execution, the heap starts filling up as new objects are created. The runtime has a garbage collector that periodically deallocates objects from the heap. An object is eligible for deallocation as soon as it’s not referenced by anything that’s itself “alive”. Consider the following example:

using System;
using System.Text;
class Test
{
  static void Main()
  {
    StringBuilder ref1 = new StringBuilder ("object1");
    Console.WriteLine (ref1);
    // The StringBuilder referenced by ref1 is now eligible for GC.
    StringBuilder ref2 = new StringBuilder ("object2");
    StringBuilder ref3 = ref2;
    // The StringBuilder referenced by ref2 is NOT yet eligible for GC.
    Console.WriteLine (ref3); // object2
  }
}

We start by creating a StringBuilder object referenced by the variable ref1, and then write out its content. That StringBuilder object is then immediately eligible for garbage collection, because nothing subsequently uses it.

Then, we create another StringBuilder referenced by variable ref2, and copy that reference to ref3. Even though ref2 is not used after that point, ref3 keeps the same StringBuilder object alive—ensuring that it doesn’t become eligible for collection until we’ve finished using ref3.

Value-type instances (and object references) live wherever the variable was declared. If the instance was declared as a field within an object, or as an array element, that instance lives on the heap.

The heap also stores static fields and constants. Unlike objects allocated on the heap (which can get garbage-collected), these live until the application domain is torn down.

Overloading and Overriding: What is the difference?

Overloading and overriding are different aspects of polymorphism.


Overloading is when you define two methods with the same name in the same class but with different signatures. Signature includes method name and parameters. These functions can be part of base class or derived class. Overloading is resolved at compile time.
Overloading is also called static/early binding polymorphism. Overloading is compile time binding.

Overriding is when you redefine a method that has already been defined in a parent class with their same signature. We can override a function in base class by creating a similar function in derived class and by use virtual/override keywords. 
Base class method has to be marked with virtual keyword and we can override it in derived class using override keyword. 
Derived class method will completely override base class method i.e. when we refer base class object created by casting derived class object a method in derived class will be called.
Overriding is mostly resolved at runtime, depending on language and situation. C++ and C# for example, are tricky in this respect, as methods are by default not overridable at runtime, but compile time (the virtual keyword controls this behavior). The C# compiler will however issue warnings when it suspects you have got it wrong.
Overriding is also called dynamic/late binding polymorphism. Overriding is runtime binding. 

Example:

Base Class:
-------------------------------
public class BaseClass
{
  public virtual void Method1()
  {
    Print("Base Class Method");
  }
}

Derived class
-----------------------------

public class DerivedClass: BaseClass
{
  public override void Method1()
  {
    Print("Derived Class Method");
  }
}

Usage
--------------------------
public class Sample
{
  public void TestMethod()
  {
    DerivedClass objDC = new DerivedClass();
    objDC.Method1();
    BaseClass objBC = (BaseClass)objDC;
    objDC.Method1();
  }
}


Result
---------------------
Derived Class Method
Derived Class Method

Differentiate between as and cast operators


Most people will tell you that the difference between "(Alpha) bravo" and "bravo as Alpha" is that the former throws an exception if the conversion fails, whereas the latter returns null. Though this is correct, and this is the most obvious difference, it's not the only difference. There are pitfalls to watch out for here.

First off, since the result of the "as" operator can be null, the resulting type has to be one that takes a null value: either a reference type or a nullable value type. You cannot do "as int", that doesn't make any sense. If the argument isn't an int, then what should the return value be? The type of the "as" expression is always the named type so it needs to be a type that can take a null.

Second, the cast operator, means two contradictory things: "check to see if this object really is of this type, throw if it is not" and "this object is not of the given type; find me an equivalent value that belongs to the given type". The latter meaning of the cast operator is not shared by the "as" operator. If you say:

short s = (short)123;
int? i = s as int?;


then you're out of luck. The "as" operator will not make the representation-changing conversions from short to nullable int like the cast operator would. 

Similarly, if you have class Alpha and unrelated class Bravo, with a user-defined conversion from Bravo to Alpha, then "(Alpha) bravo" will run the user-defined conversion, but "bravo as Alpha" will not. The "as" operator only considers reference, boxing and unboxing conversions.

And finally, of course the use cases of the two operators are superficially similar, but semantically quite different. A cast communicates to the reader "I am certain that this conversion is legal and I am willing to take a runtime exception if I'm wrong". The "as" operator communicates "I don't know if this conversion is legal or not; we're going to give it a try and see how it goes".

Differentiate between is and as operator in C#


is operator

The is operator allows us to check whether an object is compatible with a specific type. Here the phrase "is compatible" means that an object is either of that type or is derived from that type.

For eg:

int k = 0;
if (k is object)
{
Console.WriteLine("i is an object");
}

as operator

The as operator is used to perform explicit type conversion of reference type. If the type being converted is compatible with the specified type, then that conversion is successful else as operator will return a null value.

For eg:

object x = "I am here";
object y = 10;

string s1 = x as string; // here conversion is compatible so,s1="I am Here"
string s2 = y as string; // here conversion is incompatible so,s2=null

Differentiate between out and ref keywords


The out keyword causes arguments to be passed by reference, which is similar to the ref keyword, except that ref requires that the variable be initialized before being passed.

This means inside your method implementation which takes an out parameter you have to set a value before you can use it. At least you have to assign a value before you can return. 

This also means you can not use the out parameter to pass a value to the method. (With ref you can).


This also means you can not have any logically includes comparison (e.g. if (param > 0) {...}) inside your method before you assign a value to your incoming parameter.


"The ref and out keywords are treated differently at run-time, but they are treated the same at compile time. Therefore methods cannot be overloaded if one method takes a ref argument and the other takes an out argument."

To see the difference in IL, you can use Reflector to see how the IL looks like for out/ref on Value Types (in my case int32):
out: [out] int32& result
ref: int32& result

Remarks:
- Most of the Framework functions (e.g. TryParse) use out and not ref. But inside the internal implementation the Framework mainly uses ref.
- Properties can not be passed via out or ref. (Under the hood they are function calls)
- It is very handy if you have several Value Types as return values and you don't want to create a class or struct.

Differentiate between the int and Int32 datatype, or String and string (lowercase)

Int32 is the System.Int32 class, while int is an alias for System.Int32.


The same applies for String (uppercase S) which is System.String, while string (lowercase S) is an alias for System.String.

So basically int is the same thing as Int32, and string is the same thing as String. It's down to user's preference which one to use but most prefer to use int and string as they are easier to type and more familiar among C++
programmers
.