C# Interview Questions
C# Interview Questions
C# Interview Questions
Generics
Although new to the .NET platform, this concept has been around for years. Generics
is a term used to describe generic types. It greatly enhances application performance
and type safety and allows you to write highly general, flexible and safe code. It
permits classes, interfaces, structs, delegates and methods to be parameterized by
the types of data they store and manipulate.
Iterators
Iterators specify how a for-each loop will iterate over a collection and return its
internal items. They allow you to create enumerable classes with minimum coding.
Partial Classes
Partial Classes allows you to split a single type, like your class, across more than one
file (.cs). They are useful if you have extremely large, unwieldy types.
Nullable Types
Nullable types allow a variable to contain a value that is undefined. This is useful
when working with databases where the value returned might be null
Anonymous Methods
Anonymous Methods Are Inline Delegates. It enables you to pass a block of code as
a parameter. Anonymous methods enables you to directly associate a block of code
statements to a given event. You use them anywhere a delegate is used . So there is
no need to define a new method.
Static Classes
With C# 2.0, now you also can declare classes as static. This signals the compiler
that this class should not be instantiated and can only contains static members.
Property Accessor Accessibility
C# 2.0 allows a fine control over the accessibility of accessors and indexers within a
property.
Conclusion
In this article, we explored the various new features introduced in C# 2.0. In Part
two, we will explore these new features in detail.
Generics
Classes are templates that you can use to build new objects. Generics are templates
that you can use to build new classes. This code template can be applied to use the
same code repeatedly. A generic class is tied to one or more specific data types.
GenericsExample();
}
private void GenericsExample()
{
ClsGeneric<int> intGeneric = new ClsGeneric<int>(1000);
ClsGeneric<string> strGeneric = new
ClsGeneric<string>("Voila");
ClsGeneric<float> fGeneric = new ClsGeneric<float>(23.38f);
ClsGeneric<double> dGeneric = new ClsGeneric<double>(444.4);
ClsGeneric<bool> bGeneric = new ClsGeneric<bool>(true);
}
}
By using a generic type parameter T, you can write a single class that other client
code can use without incurring the cost or risk of runtime casts or boxing operations.
Iterators
In the earlier versions of C#, in order to use the for-each loop, you need to
implement the IEnumerable interface which in turn demands the implementation of
the GetEnumerator() method. This method returns an IEnumerator object using
which you can use the foreach loop.
An iterator on the other hand, enables you to support foreach iteration in a class or
struct without having to implement the entire IEnumerable interface.
Let me demonstrate this with an example :
public class StringCollection : System.Collections.IEnumerable
{
string[] names = { "Tom", "Dick", "Harry”, "Ralph", "Jack", "Jill” };
class TestStringCollection
{
static void Main()
{
// Create an instance
StringCollection strNames = new StringCollection();
Partial Classes
C# 2.0 introduces the concept of partial type definitions for classes, structs, and
interfaces that allows you to define a C# type across multiple *.cs files. This leads to
easier maintenance and development as more than one developer can
simultaneously write the code for the class.
Nullable Types
A null type is very similar to its equivalent non-nullable type. The difference lies in
how it is declared. For example : To declare an integer, you would declare it like
this :
int iVal = 1;
However in order to enable iVal to store a null value, you will declare it like this :
int? iVal = 1;
Now the way to define any valuetype as a nullable type is to define the generic
System.Nullable<T> type. So the syntax to define a nullable integer is:
System.Nullable<int> iVal;
Anonymous Methods
Anonymous methods help you reduce the coding overhead in instantiating delegates,
by eliminating the need to create a separate method. This construct allows you to
directly associate a block of code statements to a given event. In general, you can
use anonymous methods anywhere you can use a delegate. An anonymous method
consists of the keyword delegate, an optional parameter list, and a statement list
enclosed in { and } delimiters. In some cases, the anonymous methods can omit the
parameter list.
InitializeComponent();
}
}
public frmNew()
{
InitializeComponent();
class TestAnonymous
{
static void Main()
{
Static Classes
Static classes are classes that contain only static members. These static members
can be initialized only by using static constructors. The data and functions that these
classes create, can be accessed without creating an instance of the class. Static
classes are sealed so they can not be inherited. TheSystem.Math class is an example
of this construct.
Static classes can be used when there is no data or behavior in the class that
depends on object identity. One of the advantages of static classes is improved
performance. Since there is no instantiation of object, the framework maintains a
single object in memory for static members. They are loaded automatically by the
.NET Framework common language runtime (CLR) when the program or namespace
containing the class is loaded.
Creating a static class is much the same as creating a class that contains only static
members and a private constructor. A private constructor prevents the class from
being instantiated. Lets see an example of a static class.
Properties provide flexibility to read and write the values of private fields. They can
be used as though they are public data members, but they are actually special
methods called accessors. This enables data to be accessed easily while still
providing the safety and flexibility of methods.
In C# 1.x, we declare a property in our class in the following manner:
class ClsProp
{
private string strMyName = "Suprotim";
In this example, a property called StrMyName defines a get and set accessor. The
get accessor receives the accessibility level of the property itself, public in this case,
while the set accessor is explicitly restricted by applying the protected access
modifier to the accessor itself.
Note : This feature of having Accessor Accessibility was provided in C# v1.0 beta.
However Microsoft removed it before the C# v1.0 RTM as they felt it was too
complicated for developers. In C# 2.0, it has been re-introduced.
In .NET 1.1, delegates could only be created with methods whose arguments strictly
matched the signature of that delegate. With .NET 2.0, Covariance and
contravariance provide a degree of flexibility when matching delegate methods with
delegate signatures.
Advantages:
.Encapsulating the method's call from caller
.Effective use of Delegat improves the performance of application.
.used to call a method asynchronously.
Declaration:
Note:
.you can use delegeate without parameter or with parameter list
.you should follow the same syntax as in the method
(if you are reffering the method with two int parameters and int return type the delegate
which you are declaring should be the same format.This is how it
is reffered as type safe function pointer)
class Class1
{
int v1 = Int32.Parse(Console.ReadLine());
int v2 = Int32.Parse(Console.ReadLine());
}
}
Explanation:
Here I have used a small program which demonstrates the use of delegate.
The delegate "Delegate_Prod" is declared with double return type and which accepts only
two integer parameters.
Inside the Class the method named fn_Prodvalues is defined with double return type and
two integer parameters.(The delegate and method is having the same signature and
parameters type)
Inside the Main method the delegate instance is created and the function name is passed
to the
delegate instance as following.
delObj(v1,v2);
Here delegate object encapsulates the method functionalities and return the result as we
specified
in the method.
Multicast Delegate
What is Multicast Delegate? :
It is a Delegate which holds the reference of more than one methods.
Multicast delegates must contain only methods that return void, else there is a run-time
exception.
Class Class2
{
static void Method1(int x, int y) {
Console.WriteLine("You r in Method 1");
}
static void Method2(int x, int y) {
Console.WriteLine("You r in Method 2");
}
public static void Main()
{
Delegate_Multicast func = new Delegate_Multicast(Method1);
Explanation:
In the above example you can see that two methods are defined named method1 and
method2 which takes two integer parameters and return type as void.
In the main method the Delegate object is created using the following statement
Then the Delegate is added using the += operator and removed using -= operator.
#2 is right and gave acurate definition of event and event handler but since we declare a
event using delegate so we usually say a event is a delegate but from the declaration we
can see what is a delegate is the eventhandler.
Delegates are similar to function pointers of C++, they hold the address of a function,
they hide the actual information.
.Net supports 2 types of delegates:
1)Single Cast Delegate
2)Multi Cast Delegate
Multi Cast Delegate holds the addresses of more than one function.
YES,two delegates can refer the same function i.e,two delegates can hold the address of
same method.
multiple delegates and multicast delegates both are diffrent terms with diffrent aspects.
delegate having one property that it could have multiple delegates in it.it means single
delegates contain multiple delegates definition while
in other case multicast delagates means single delagates contain refrence of several
methods......
lass Design. Below is a set of birds and movements they can perform.
Birds:
Penguin:
• hopping: moves 2 ft
• flying: can't fly
Hawk:
• hopping: can't hop
• flying: moves 100 ft; won't fly if World.windSpeed > 40
Robin:
• hopping: moves 1 ft; won't hop if World.temperature < 0
• flying: moves 20 ft; won't fly if World.windSpeed > 20
Crow:
• hopping: moves 1 ft; won't hop if World.temperature < 0
• flying: moves 30 ft; won't fly if World.windSpeed > 25
Requirements:
• Create a class or set of classes in C# to represent the birds.
• Create an instance of each type of bird and add them all into a single collection. Have
each bird hop and then fly in turn, each time after the World changes. After all birds have
moved, print out the total distance that each one has moved. (See the comments in Main
below marked // TODO).
• Fill in main() to generate the desired output (which is shown under main() below).
• Use best design practices. The priority is to create maintainable code.
using System;
using System.Collections.Generic;
namespace PCD
{
World. = 20;
World. temperature windSpeed = 12;
// a storm arrives!
World.temperature = -10;
World.windSpeed = 30;
}
}
}
Desired output:
The penguin moved 4 ft.
The hawk moved 200 ft.
The robin moved 21 ft.
The crow moved 31 ft.
Yes,It is possible to have different access modifiers,but the best approach is to use all
access modifiers as public for efficient data retrieval.
public String EMPNO
{
get
{
return _empno;
}
set
{
_empno = value;
}
}
We don't specify any access modifiers on "get" and "set" individually, rather we specify
on the wrapping property name.
It is very easy, if you are using .NET Framework 2.0 or above. See
http://msdn.microsoft.com/en-us/library/75e8y5dd(VS.80).aspx
In short, the restricion is always to a more restrictive level, and only one accessor can be
modified - for instance:
public int MyInt
{
get
{ return m_MyInt; }
private set
{ m_MyInt = value; }
}
Correct me if I am wrong.
int i1 = 5;
double d1 = i1 + 0.99;
int i2 = (int)d1; //result is 5
i2 = Convert.ToInt32(d1);//result is 6
Why does cast and convert in above example have different results.
.NET Attributes provide the means for a developer to add meta-data that describes, or
annotates, specific elements of code such as classes, methods, properties, etc. At compile
time, the resulting metadata is placed into the Portable Executable (PE)file, along with
the Microsoft Intermediate Language (MSIL). Once metadata is in the PE, other .NET
programs may access it using the .NET Reflection API
Serialization :------------------Serialization in .NET allows the programmer to take an
instance of an object and convert it into a format that is easily transmittable over the
network, or even stored in a database or file system. This object will actually be an
instance of a custom type, including any properties or fields you may have set. A few
examples I can think of include the ability to send an instance of your object to another
portion of a local or remote application, such as over a Web service. Another example of
when to choose to serialize objects is for data within objects that would normally be
stored in a database, but these pieces of data do not need to be stored individually (their
own fields in your tables). Streamline the database design by only holding those pieces of
data for each record you need to query on, and the rest of the pieces can simply be
serialized within a custom type and stored as a complete object within the
database.Advantages of Binary Serialization --------------------------------------------All
members, no matter if they are read-only will be serialized. Greater performance*
Advantages of XML Serialization -------------------------------------------Greater flexibility
of object sharing and usage (interoperability) No strict binary dependence Human
readable #region Binary Serializerspublic static System.IO.MemoryStream
SerializeBinary(object request)
INDEXER IN C#:
In c# introduce new concept is Indexer. This is very useful for some situation. Let as
discuss something about Indexer.
• Indexer Concept is object act as an array.
• Indexer an object to be indexed in the same way as an array.
• Indexer modifier can be private, public, protected or internal.
• The return type can be any valid C# types.
• Indexers in C# must have at least one parameter. Else the compiler will
generate a compilation error.
this [Parameter]
{
get
{
// Get codes goes here
}
set
{
// Set codes goes here
}
}
For Example:
using System;
using System.Collections.Generic;
using System.Text;
namespace Indexers
{
class ParentClass
{
private string[] range = new string[5];
public string this[int indexrange]
{
get
{
return range[indexrange];
}
set
{
range[indexrange] = value;
}
}
}
/* The Above Class just act as array declaration using this pointer */
class childclass
{
public static void Main()
{
ParentClass obj = new ParentClass();
obj[0] = "ONE";
obj[1] = "TWO";
obj[2] = "THREE";
obj[3] = "FOUR ";
obj[4] = "FIVE";
Console.WriteLine("WELCOME TO C# CORNER HOME PAGE\n");
Console.WriteLine("\n");
All indexers should accept at least one parameter. Indexers cannot be static. This is
because static methods do not have access to ‘this’. The ‘this’ keyword indicates an
instance of the current class.
Interface:
-- If your child classes should all implement a certain group of methods/functionalities,
but each of the child classes is free to provide its own implementation, then use
interfaces.
For e.g., if you are implementing a class hierarchy for vehicles, implement an interface
called "Vehicle", which has properties like Colour, MaxSpeed etc., and methods like
Drive(). All child classes like "Car", "Scooter", "AirPlane", "SolarCar" etc. should derive
from this base interface, but provide a seperate implementation of the methods and
properties exposed by Vehicle.
-- If you want your child classes to implement multiple, unrelated functionalities, in short
multiple inheritance, use interfaces.
For e.g., if you are implementing a class called "SpaceShip", that has to have
functionalities from a "Vehicle", as well as that from a "UFO", then make both "Vehicle"
and "UFO" as interfaces, and then create a class "SpaceShip" that implements both
"Vehicle" and "UFO".
Abstract Classes
-- When you have a requirement where your base class should provide default
implementation of certain methods, whereas other methods should be open to being
overridden by child classes, use abstract classes.
For e.g., again take the example of the "Vehicle" class above. If we want all classes
deriving from "Vehicle" to implement the "Drive()" method in a fixed way, whereas the
other methods can be overridden by child classes. In such a scenario, we implement the
"Vehicle" class as an abstract class with an implementation of "Drive", while leave the
other methods / properties as abstract so they could be overridden by child classes.
-- The purpose of an abstract class is to provide a common definition of a base class that
multiple derived classes can share. For example, a class library may define an abstract
class that is used as a parameter to many of its functions, and require programmers using
that library to provide their own implementation of the class by creating a derived clas
If we have 2 interfaces, say Ix and Iy, and also we have one method in both interfaces
with same signature. Now we have to inherit a class from both interfaces so how to
access the method of interface Ix or that of Iy.
Example
interface lx
{
void Amit();
}
interface ly
{
void Amit();
}
class Dwivedi:lx,ly
{
public static void main()
{
lx k;
ly l;
k.Amit();
l.Amit();
}
}
That's the right example we can use for implementing both interfaces
· Inheritance relates to the programmer's ability to specify that one class have a kind-
of relationship with another class. A derived class should require no more and promise no
less than its base class on any inherited interfaces. When a programmer has a reference to
a derived class, the programmer can always treat that class as though it is the base class.
This is called upcasting.
· Managed code is just code that is running under the guidance of the CLR and is
therefore being managed by the CLR. In a managed code environment, a number of rules
are in place to ensure that all applications behave in a globally uniform manner,
regardless of the language they were written in.
· To make it easy for language writers to port their languages to .NET, Microsoft
developed a language akin to assembly language called Microsoft intermediate language
(MSIL). To compile applications for .NET, compilers take source code as input and
produce MSIL as output. MSIL itself is a complete language that you can write
applications in.
· In a .Net PE file (Assembly), the operating system can't execute the MSIL code, so
from the entry point, it jumps to the _ CorExeMain function in mscoree.dll. The _
CorExeMain function starts the execution of the MSIL code that was placed in the PE.
· Three different JITters can be used to convert the MSIL into native code, depending
on the circumstances:
2. JIT: The default JITter is called at run time -each time a method is invoked for the first
time.
3. EconoJIT: Another run-time JITter, the EconoJIT is specifically designed for systems
that have limited resources—for example, handheld devices with small amounts of
memory. It uses code pitching. Code pitching allows the EconoJIT to discard the
generated, or compiled, code if the system begins to run out of memory. The benefit is
that the memory is reclaimed. However, the disadvantage is that if the code being pitched
is invoked again, it must be compiled again as though it had never been called.
· Unmanaged code is code that is not controlled by the .NET runtime. This code is
still run by the .NET runtime. However, unmanaged code doesn't have the advantages
that managed code has, such as garbage collection, a unified type system, and metadata.
When you want to call COM components by managed code, you do this by creating a
.NET wrapper for the COM component so that the managed client thinks it's working
with a .NET class. And when a COM component wants to call a .NET component, it's
solved using a reciprocal approach: a COM client is fooled into thinking it's using a COM
server, which is actually a .NET service of some sort.
output.WriteLine("Hello, World");
In the Start menu's Run dialog box, type ildasm and click OK. You'll see a nondescript
application with a few menu options. At this point, from the File menu, click Open and
specify the .Net assembly (Exe/DLL). To tell whether an EXE or DLL is managed,
attempt to open it with ILDASM. If the file is a valid managed file, it will be opened. If
it's not, you'll receive an error message stating that <your file> has no valid CLR header
and cannot be disassembled
· CTS is responsible for defining the types that can be used across .NET languages.
The CTS separate types into two categories. Value types (Primitive type) and reference
types. Variables of value types are stored in the stake and variables of reference types are
stored on the heap. Value types variables cannot be null but the reference types variables
can be. Reference types are type-safe pointers. All types are ultimately derived from
System.Object type.
When converting from a value type to a reference type—there is no explicit cast needed.
However, when unboxing—the cast is needed. This is because in the case of unboxing,
an object could be cast to any type. Therefore, the cast is necessary so that the compiler
can verify that the cast is valid per the specified variable type.
C# Alias
Description
System.Object
object
System.String
string
String
System.SByte
sbyte
System.Byte
byte
System.Int16
short
System.UInt16
ushort
System.Int32
int
uint
System.Int64
long
System.UInt64
ulong
System.Char
char
System.Single
float
System.Double
double
IEEE 64-bit float (8 bytes)
System.Boolean
bool
System.Decimal
decimal
128-bit data type exact to 28 or 29 digits—mainly used for financial applications where a
great degree of accuracy is required. (16 bytes)
· C# Access Modifiers
Public
Member is accessible from outside the class's definition and hierarchy of derived classes.
Protected
The member is not visible outside the class and can be accessed by derived classes only.
Private
The member cannot be accessed outside the scope of the defining class.
Internal
· Command-Line Parameters
· C# included a mechanism by which you can define more than one class with a Main
method. To specify which Main() method to call at compilation you can use [csc
MultipleMain.cs /main:<ClassName>] switch.
class B : A
}
}
· Read-Only Fields: When you define a field with the readonly keyword, you have
the ability to set that field's value in one place: the constructor. The read-only fields that
we defined are instance fields.
· Static Constructors: Static constructors are constructors that are used to initialize
static fields, read-only or otherwise.
· In case of inheritance, the base class's constructor cannot be inherited. Each class
must implement its own constructor irrespective of its base class.
Function Definition:
public void GetName(ref int age)
Function Calling:
int age;
Object.GetName(ref age);
When you use the ref keyword, you must initialize the passed arguments before calling
the method.
Out Keyword: Use 'Out' keyword in place of 'ref' and you would not required to initialize
the passed arguments before calling the method.
· In case of overloading, it's not sufficient to have only return type different, but
method's argument list must be different.
}
Function Calling:
string a;
string b;
Object.GetName(a,b);
use GetLength() method of passed param array to find out number of elements sent.
· Overriding: Use 'new' keyword in derived class method when you are going to
override the base class method.
· When you have an object of a class, which has a static method, even though you
cannot call the method by object. You still have to call that method by class name
(ClassName.MethodName() not like ObjectName.Method()).
· A static method can access any static member within the class, but it cannot access
an instance member.
· Value Variable In Properties: Even though you do not declare a variable named
'value' in code, but you can still use that variable in properties set segment, because
compiler injects this variable as an argument of a method in IL code, which represents
your set segment of the property.
· Derived class can inherit and override properties just as it could any other member
from the base class. But, if the base class' property contains both get and set segment, you
have to implement both these segment in your derived class version.
· Arrays
int[] numbers;
When declaring the array as a member of a class, you need to declare and instantiate the
array in two distinct steps because you can't instantiate an object until run time. (Arrays
are object of System.Array class)
Length() method of an array object return total number of elements that array contains.
Whereas GetLenght() return length or upper bound of the each dimension.
The number of dimensions in an array is called an array's rank, and rank is retrieved
using the Array.Rank property.
A jagged array is simply an array of arrays.
int[][] jaggedArray;
· Interface: In terms of C++, an interface is basically an abstract class with only pure
virtual methods. All interface methods are public by definition.
· Is Operator: The 'is' operator enables you to check at run time whether one type is
compatible with another type.
if (myControl is ISerializable)
{} else {}
If Obj1 and Obj2 were compatible in types then casting would be done, unless Obj2 will
contains a null value.
· When a class implements an interface, by default all the implemented methods are
visible out side the class, because those methods are declared public in the interface. If
you want to hide those methods you have to remove the access modifier 'public' in class
implementation and qualify the members name with interface name.
{void Bind();}
void IDataBound.Bind()
{}
This is also used to solve the ambiguity between more then one interfaces, a class is
implementing. For example, a class is implementing more then one interfaces and each is
providing the a method with same name, then you can implement each method by its own
interface qualifier name and at run time you can cast the class object to that particular
interface, who's method you want to call. So, always cast the object to the interface
whose member you're attempting to use.
3) Now you derived a class both from base class and interface, and you do not
implements method Foo() of the interface in that derived class.
4) When you make an object of that derived class and try to call that method Foo(), it
will compile and run without any error (despite the fact that you have to implements all
the methods of an interface in a implementing class). Because when compiler searches
the Foo() method for the interface, it founds that base class method Foo() as implemented
and code works. But it does not give desirable results. And when you cast the derived
class object to the interface type and try to call Foo(), you would probably get the error.
3) You have a class derived from that base class, and it also have its own method
named Foo() (Declared with 'new' keyword, overriding base class method).
4) Now when you try to call Foo() method by the derived class object, which method will
be called ? It depends on what reference you have. If you have a reference to the derived
class object, its Foo() method will be called. However, when you explicitly cast the
derived class object to the interface, the implemented method of the interface will be
called (base class method).
· You can combine the two or more interfaces in one, so that a class, which is
implementing the combined interface, also implements all the methods of other interfaces
as well.
public interface IA
public interface IB
C# Operators:
(), x.y, a[x], ++, --, new, typeof, sizeof (Works on only value types), checked, unchecked,
<operator>= (i.e. +=, -=), >, <, >=, <=, ==, !=,
Object1.Equals(Object2)
It returns true if both object belongs to same class or have same members. When you
compare two objects like (Object1 == Object2) you will get a false value. Because C#
compare objects by their memory addresses and that is different for any two objects.
· When you assign one object to another, basically you are not copying one object to
another. What actually you are doing is that you are making same memory reference for
both of the objects. So that if you make change in one object, it will be reflected in
another one also.
For example:
Obj1 = Obj2;
Now both objects are pointing the same memory location. And the object Obj1 is
destroyed and eventually collected by GC.
It also happens when you pass the object to a method. When this is the case the object's
reference is actually passes to method, so that any changes (in value of members) in the
passed object in the method code also reflect in the actual object in calling program.
· The continue statement stops the current iteration and returns control back to the top
of the loop for the next iteration.
· If the return statement is a try block that contains an associated finally block,
control is actually passed to the first line of the finally block, and when that block of code
finishes, control is passed back to the caller.
· If you put more then one catch block handling different exceptions, you have to put
those block in a order that all the derived exception (from System.Exception) come first,
then at last the type of base class (System.Exception) exception. If not so, then the other
derived exceptions would be unreachable.
· Operator Overloading:
Generic syntax is:
All overloaded operator methods must be defined as public and static. The number of
arguments passed (object1, object2) depends on the type of operator being overloaded.
If the operator being overloaded is a binary operator, the first argument must be the same
type as that of the enclosing class and the second argument can be any type.
Binary operands: +, -, *, /, %, &, |, ^, <<, >>, ==, !=, >, <, >=, <=
When you overload a binary operator, its compound assignment equivalent is implicitly
overloaded. For example, if you overload the + operator, the += operator is implicitly
overloaded in that the user-defined operator+ method will be called. Also, an operator's
syntax can't be modified. You can't change the binary * operator to take three arguments
when, by definition, its syntax calls for two operands.
· User-Defined Conversions:
The implicit keyword means that the cast is not required by the client and will occur
automatically. Conversely, using the explicit keyword signifies that the client must
explicitly cast the value to the desired type.
· Delegates:
Callback methods are used when you need to pass a function pointer to another function
that will then call you back (via the passed pointer).
· Events:
· Threading:
· Context Switching:
When the hardware timer signals the interrupt, the processor saves all registers for the
current thread onto the stack. Then the processor moves those same registers from the
stack into a data structure called a CONTEXT structure. When the processor wants to
switch back to a previously executing thread, it reverses this procedure and restores the
registers from the CONTEXT structure associated with the thread. This entire procedure
is called context switching.
· Through synchronization, you specify critical sections of code that can be entered
by only one thread at a time, thereby guaranteeing that any temporary invalid states of
your object are not seen by the object's clients. We achieve the synchronization between
threads by Monitor class or Mutex Class.
· Reflection:
.NET allows you to write code to access an application's metadata through a process
known as reflection. Reflection is the ability to discover type information at run time. The
reflection API let's you do such things as iterate an assembly's modules, iterate an
assembly's types, and retrieve the different design-time characteristics of a type.
Advanced reflection tasks include using reflection to dynamically invoke methods and
use types (via late binding) and even to create and execute MSIL code at run time. We
have to use following namespaces to works the code:
using System;
using System.Diagnostics;
using System.Reflection;
int i = 6;
Type t = i.GetType()
Type t = Type.GetType("System.Int32");
(Note that you cannot use the C# aliases when calling the Type.GetType method.)
o You can interrogate about a type by first creating a object of that type and then
using its methods, which all start from prefix 'Is' (i.e. type.IsByRef).
Assembly a = Assembly.LoadFrom("MyApp.Exe");
foreach(Type t in types)
{t.FullName;}
Assembly a = Assembly.LoadFrom("MyApp.Exe");
{m.Name;}
· Unmanaged code refers to code that is not managed, or controlled, by the .NET
runtime.
Attributes are used to provide design-time information for a C# type. Through reflection,
this information can later be queried at run time. C# makes use of an attribute to allow
you to describe the DLL function that the application will call to the compiler. This
attribute is called the DllImport attribute, and its syntax is shown here:
using System.Runtime.InteropServices;
[DllImport("DllName")]
o Not only can a C# application call a DLL function, but the DLL function can also
call designated C# methods in your application. You do it by using function callbac.
o Marshalling: Any time you call a DLL function, .NET has to marshal the
parameters to that function and the return value back to the calling .NET application. It
happens almost implicitly because .NET has a defined default native type for each .NET
type.
o An unmanaged code is a code for which the .NET runtime will not be controlling
the allocation and de-allocation of memory. You write unsafe code by using two
keywords: unsafe and fixed. The unsafe keyword specifies that the marked block will run
in an unmanaged context. The fixed keyword is responsible for the pinning of managed
objects. Pinning is the act of specifying to the garbage collector (GC) that the object in
question cannot be moved. As it happens, during the execution of an application, objects
are allocated and de-allocated and "spaces" in memory open up. Instead of memory
becoming fragmented, the .NET runtime moves the objects around to make the most
efficient use of memory.
o Pointers in C# can be acquired only for value types, arrays, and strings. Pointers
operators in c# are similar to C/C++:
Operator
Description
&
The address-of operator returns a pointer that represents the memory address of the
variable.
The de-reference operator is used to denote the value pointed at by the pointer.
->
The de-referencing and member access operator is used for member access and pointer
de-referencing.
· COM Interoperability:
A .NET application that needs to talk to a COM component cannot directly consume the
functionality that's exposed by that component, because the .NET runtime is designed to
work with components that have metadata, whereas COM is designed to work through
the Registry and a series of interrogatory methods that are implemented by the
component. Therefore, we need to enable a COM component to generate some metadata
for it. In the case of a COM component, this metadata layer is used by the runtime to
determine type information. This type information is then used at run time to manufacture
what's called a runtime callable wrapper (RCW). The RCW handles the actual activation
of the COM object and handles the marshalling requirements when the .NET application
interacts with it. The RCW also does tons of other chores, such as managing object
identity, object lifetimes, and interface caching. The RCW serves the purpose of giving
the .NET application the notion that it's interacting with a managed .NET component, and
it gives the COM component in the unmanaged space the impression that a traditional
COM client is calling it. The TLBIMP utility is used to read and generate metadata of a
COM component. It read the COM type-lib and generates a corresponding metadata
wrapper in the form of a DLL.
One RCW instance is created for each instance of the COM object. The .NET runtime is
concerned only with managing the lifetime of the RCW and garbage collects the RCW.
It's the RCW that takes care of maintaining reference counts on the COM object that it's
mapped to, thereby shielding the .NET runtime from managing the reference counts on
the actual COM object. Any time a COM method raises an error, the COM error is
trapped by the RCW. This error is then converted into an equivalent COMException
class. The .NET client can catch the error with the usual try-catch exception handling
mechanism, and the client has access to the error number, description, the source of the
exception etc.
· We can create an assembly by Assembly Generation tool called al.exe. This tool
takes one or more .Net files or module and generates a single assembly.
· By default, all the .Net assemblies are private. To share an assembly, you must
create a shared name (also known as a strong name) for the assembly by using the Strong
Name tool (sn.exe) that accompanies the .NET SDK. Using this tool first we generates a
key file. That key file contains a globally unique identifier. Then we specify this key file
into one of modules that the assembly is going to contains.
gacutil -i HelloWorld.DLL
(If you don't specify the version, all the assemblies with the same name would be
uninstalled.)
Quick Fix Engineering updates, or hot fixes typically doesn't modify the code's interface,
the chances that client code will be adversely affected are minimal. Therefore, the default
versioning policy is to automatically associate all client code to the new "fixed" version
of the code unless a configuration file exists for the application that explicitly associates
the application with a specific version of an assembly. A new version of an assembly is
considered to be a QFE if the only part of the version number that changed is the revision
part.