DOT.NET http://blogs.msdn.com/b/csharpfaq/
http://www.aisto.com/roeder/dotnet/ Reflector
http://www.codeproject.com/useritems/codebased.asp Web Services
http://www.bitwidgets.com BitDiffer Assembly Comparison Tool
http://www.codeproject.com/useritems/Sorting_with_Objects.asp Sorting the objects with multiply fields
http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx
http://code.msdn.microsoft.com/sourceanalysis StyleCop
http://msdn.microsoft.com/en-us/library/bb429476(VS.80).aspx FxCop
Local files C#1 C#2
.NET 4
http://iamnotmyself.com/2011/03/28/an-exploration-of-dynamic-in-net-4/
http://blogs.msdn.com/b/csharpfaq/archive/2010/04/12/get-ready-for-c-4-0.aspx
Unlike a variable declared with the var keyword, you don't have to initialize a dynamic variable when declaring it
DataType[] VariableName = new DataType[Number];
var VariableName = new DataType[Number];
dynamic VariableName = new DataType[Number];
int[] lengths = new int[] { 112, 108, 145, 121, 100 };
http://www.csharpkey.com/csharp/index.htm
__CLR_VER defines the version of the common language runtime used when the application was compiled. The value returned will be in the following format: Mmmbbbbb where,
M is the major version of the runtime
mm is the minor version of the runtime
bbbbb is the build number.
// clr_ver.cpp
// compile with: /clr
using namespace System;
int main() {
Console::WriteLine(__CLR_VER);
}
The C# keywords used to specify that a parameter is being passed by reference are ref and out. The difference between the keywords is that parameters passed using ref must be initialized to some value while those passed using out do not have to be.
C# provides the option to explicitly detect or ignore overflow conditions in expressions and type conversions. Overflow conditions detected in code throw a System.OverFlowException. Since overflow detection causes a performance hit it can be explicitly enabled by using the /checked+ compiler option. One can also mandate code that must always be checked for overflow conditions by placing it in a checked block or that must always be ignored with regards to overflow detection by placing it in an unchecked block.
The Stack is self-maintaining, meaning that it basically takes care of its own memory management. When the top box is no longer used, it's thrown out. The Heap, on the other hand, has to worry about Garbage collection (GC) - which deals with how to keep the Heap clean.
What goes on the Stack and Heap?
We have four main types of things we'll be putting in the Stack and Heap as our code is executing: Value Types, Reference Types, Pointers, and Instructions.
Value Types: (because they are from System.ValueType):
The Size and Range of C# Integral Types
The Floating Point and Decimal Types with Size, precision, and Range
In C#, all the "things" declared with the following list of type declarations are Value types (because they are from System.ValueType):
bool
enum
struct
Reference Types:
All the "things" declared with the types in this list are Reference types (and inherit from System.Object... except, of course, for object which is the System.Object object):
class
interface
delegate
object
string (string with a verbatim literal, like this: @"c:\topdir\subdir\subdir\myapp.exe")
When we make a method call here's what happens:
Space is allocated and the method itself is copied from the instance of our object to the Stack for execution (called a Frame). This is only the bits containing the instructions required to execute the method and includes no data items.
The calling address (a pointer) is placed on the stack. This is basically a GOTO instruction so when the thread finishes running our method it knows where to go back to in order to continue execution. (However, this is a nice-to-know, not a need-to-know, because it will not affect how we code.)
Space is allocated for our method parameters and they are copied over. This is what we want to look at more closely.
Control is passed to the base of the frame and the thread starts executing code. Hence, we have another method on the "call stack".
Passing Value Types.
First, when we are passing a value types, space is allocated and the value in our type is copied to the new space on the stack. The point is that any value type parameters passed into a method are carbon copies and we count on the original variable's value to be preserved.
One thing to keep in mind is that if we have a very large value type (such as a big struct) and pass it to the stack, it can get very expensive in terms of space and processor cycles to copy it over each time. The stack does not have infinite space and just like filling a glass of water from the tap, it can overflow. A struct is a value type that can get pretty big and we have to be aware of how we are handling it.
So how do we get around this problem? By passing a reference to the original value type as follows:
public void Go(){
MyStruct x = new MyStruct();
DoSomething(ref x);
}
As a general practice, if we plan on ever copying of our objects, we should implement (and use) ICloneable. This enables our reference types to somewhat mimic the behavior of a value type. As you can see, it is very important to keep track of what type of variable we are dealing with because of differences in how the memory is allocated for value types and reference types.
. A collection such as an List<> stores data as 'generic objects' and boxing and unboxing operations may be used to store and retrieve data from a collection. During process of boxing and unboxing, it may be possible that the performance of conversion is being affected due the large number of items stored in a collection
When we box/unbox a Value Type, the compiler insert an specific box/unbox IL instruction which, in runtime, 'makes' the object wrapper that reference to that Value Type. This kind of operation must make a lot of manipulation:
Pop the Value from the evaluator stack. (May be skipped by the jitter optimizer)
Store the popped value in a safety place.
Construct the wrapper structure and make this point to the popped value.
Push the wrapper to evaluator stack. (May be skipped by the jitter optimizer)
it is very efficient to store 'references' types in collections than storing value types.
an access modifier meaning that a class member can be accessed from other classes. When used on a class, it means that the class can be accessed by DLLs outside of the Assembly (which is commonly a *.exe or *.dll file).
When there is no need to instantiate an object, you can create static class members.
Use static constructor to initialize static fields in a class. You declare a static constructor by using the keyword static just in front of the constructor name. A static constructor is called before an instance of a class is created, before a static member is called, and before the static constructor of a derived class. They are called only once.
structs can not have destructors. Also, structs cannot inherit another class or struct or be inherited from. However, a struct may implement multiple interfaces.
The only thing it contains are definitions of events, indexers, methods and/or properties.
interfaces must be implemented by derived classes and structs
constructors are not inherited
Only methods that are declared as virtual can be overridden in subclasses
class A {
public void F() {...}// cannot be overridden
public virtual void G() {...}// can be overridden in a subclass
}
Overriding methods must be declared as override
class B : A {
public void F() {...}// warning: hides inherited F() ??use
new public void G() {...}// warning: hides inherited G() ??use
new public override void G() {// ok: overrides inherited G... base.G();// calls inherited G()
}
It allows you to invoke derived class methods through a base class reference during run-time. This is handy when you need to assign a group of objects to an array and then invoke each of their methods. They won't necessarily have to be the same object type. However, if they're related by inheritance, you can add them to the array as the inherited type. Then if they all share the same method name, that method of each object can be invoked
public class Square : DrawingObject
{
public override void Draw()
{
Console.WriteLine("I'm a Square.");
}
}
public class DrawDemo
{
public static int Main( )
{
DrawingObject[] dObj = new DrawingObject[4];
dObj[0] = new Line();
dObj[1] = new Circle();
dObj[2] = new Square();
dObj[3] = new DrawingObject();
foreach (DrawingObject drawObj in dObj)
{
drawObj.Draw();
}
return 0;
}
}
Constructors
Destructors
Fields
Methods
Properties
Indexers
Delegates
Events
Nested Classes
Using the base keyword, you can access any of a base class public or protected class members.
private enum CarTypes
{
Lotus = 0,
Morgan = 1,
Atom = 2
}
private void button1_Click(object sender, EventArgs e)
{
CarTypes myCarType = CarTypes.Morgan;
textBox1.Text = Enum.GetName(typeof(CarTypes), myCarType) + ", " + myCarType.ToString() + ", " + (myCarType==CarTypes.Morgan).ToString();
myCarType = (CarTypes)Enum.Parse(typeof(CarTypes), "Atom");
textBox1.Text += "\r\n" + Enum.GetName(typeof(CarTypes), myCarType) + ", " + myCarType.ToString() + ", " + (myCarType == CarTypes.Atom).ToString();
myCarType = (CarTypes)Enum.Parse(typeof(CarTypes), "loTus", true);
textBox1.Text += "\r\n" + Enum.GetName(typeof(CarTypes), myCarType) + ", " + myCarType.ToString() + ", " + (myCarType == CarTypes.Lotus).ToString();
}
Output:
Morgan, Morgan, True
Atom, Atom, True
Lotus, Lotus, True
Delegates can be understood as intelligent containers that hold references to methods, as opposed to containers that hold references to objects. Delegates can contain references to zero, one, or many methods. Methods to be called by a delegate must be registered with a delegate instance. When registered, the method is added to the delegate's internal collection of method references. Delegates can hold references to static methods or instance methods in any class visible to the delegate instance. Delegate instances can call their referenced methods either synchronously, or asynchronously. When called asynchronously, the methods execute on a separate thread pool thread. When a delegate is invoked ("called"), then all methods referenced by the delegate are called automatically by the delegate.
Delegates cannot contain references to just any method. Delegates can hold references only to methods defined with a method signature that exactly matches the signature of the delegate.
Consider the following delegate declaration:
public delegate void MyDelegate(string myString);
Notice that the delegate declaration looks like a method declaration, but with no method body.
The signature of the delegate determines the signature of methods that can be referenced by the delegate. So, the sample delegate above (MyDelegate) can hold references only to methods that return void while accepting a single string argument. Consequently, the following method can be registered with an instance of MyDelegate:
private void MyMethod(string someString) { // method body here. }
The following methods, however, cannot be referenced by a MyDelegate instance because their signatures do not match that of MyDelegate.
private string MyOtherMethod(string someString) {// method body here. }
private void MyOtherMethod(string someString, int someInt) { // method body here. }
After a new delegate is declared, an instance of that delegate must be created so that methods can be registered and ultimately invoked by the delegate.
// instantiate the delegate and register a method with the new instance.
MyDelegate del = new MyDelegate(MyMethod);
After a delegate is instantiated, additional methods can be registered with the delegate instance, like this:
del += new MyDelegate(MyOtherMethod);
At this point, the delegate can be invoked, like this:
del("my string value");
And, because both MyMethod and MyOtherMethod are registered with the MyDelegate instance (named del), that instance will invoke both MyMethod and MyOtherMethod when the above line executes, passing each the string value, "my string value."
There are six sets of collection classes, and they differ in how data is inserted, stored, and retrieved. Each of these classes is in the System.Collections.Generic namespace.
We start with the Collection Generic Class, which provides the base class for a generic collection:
Collection<string> dinosaurs = new Collection<string>();
dinosaurs.Add("Psitticosaurus");
dinosaurs.Add("Caudipteryx");
dinosaurs.Add("Compsognathus");
dinosaurs.Add("Muttaburrasaurus");
The Collection class can be used immediately by creating an instance of one of its constructed types; all you have to do is specify the type of object to be contained in the collection. In addition, you can derive your own collection type from any constructed type, or derive a generic collection type from the Collection class itself.
The Collection class provides protected methods that can be used to customize its behavior when adding and removing items, clearing the collection, or setting the value of an existing item.
Most Collection objects can be modified. However, a Collection object that is initialized with a read-only IList object cannot be modified.
Elements in this collection can be accessed using an integer index. Indexes in this collection are zero-based.
Collection accepts a null reference as a valid value for reference types and allows duplicate elements.
This base class is provided to make it easier for you to create a custom collection. You are encouraged to extend this base class instead of creating your own.
List Collections: List<T>
The List<T> class has properties that make it behave similar to an array, the key difference being that it expands automatically as elements are added. List<T> can also shrink via calls to its TrimToSize() method or Capacity property. The corresponding non-generic class would be ArrayList.
Each element can be accessed by the index representing its position, e.g. List[6].
List<T> supports a Sort() method. Items must implement IComparable to be sortable. To search List<T>, you use the Contains(), IndexOf(), LastIndexOf() or BinarySearch() methods. BinarySearch() requires that the elements be sorted. You can also find multiple items with FindAll(), using a predicate parameter which returns a boolean.
Dictionary Collections: Dictionary<TKey, TValue>
Unlike List Collections, Dictionary classes store name - value pairs. The <name> parameter functions as a unique key that is used to look up it's corresponding value. The key can be any data type. The corresponding non-generic class is Hashtable.
You can add an item via the Add(key, value) method, or you can use the indexer: dictionary[key]=value. The indexer does not require an integer - the index type is specified by the first type parameter, TKey, when the Dictionary was created. An additional feature is the re-use of the same index. When you use dictionary[key]=value, instead of throwing an out of bounds exception, the Dictionary inserts a new element. If you then invoke dictionary[key]=value with the same key, the specified key already exists, so the Dictionary updates the existing element with the new value.
To deal with only the keys or elements in a Dictionary, you have the Keys and the Values properties. These return data type ICollection, which is a generic type. The data returned by these properties is a reference to the data in the original Dictionary, so changes therein are automatically reflected in the ICollection type returned by the Keys or Values properties.
Sorted Collections: SortedDictionary<TKey, TValue> and SortedList<T>
The sorted generic collection class elements are sorted by key for the SortedDictionary, and by value for SortedList. A foreach iteration returns the elements sorted in key order. With SortedList<T>, the Keys and Values properties return IList<TKey> and IList<TValue> respectively.
Stack Collections: Stack<T>
The Stack generic Collection is designed for last in, first out operations. It's two key methods are Push() and Pop(). Push() places elements into the collection; they do not have to be unique. Pop() retrieves -- and removes -- an element in the reverse order of how it was added. Just think of a "Stack" of plates. You always get the last one that was added off the top with Pop().
Queue Collections: Queue<T>
Queue Collections are identical to Stack Collections except that they follow a First in, First out pattern. The Queue<T> collection class behaves like a circular array. You place types into it at one end using the Enqueue() method, and you remove them from the other end with Dequeue(). As with Stack<T>, the objects do not have to be unique, and the class automatically increases in size as required. You can recover the capacity with TrimToSize().
Here at Eggheadcafe.com Dan Schwieg has an excellent article about the Blocking Queue, a non-generic implementation that can easily be converted to its generic counterpart.
Linked Lists: LinkedList<T>
The LinkedList<T> class enables both forward and reverse traversal with properties Next and Previous, and methods AddAfter(), AddFirst(), AddBefore(), AddHead(), AddLast() and AddTail(). LinkedList<T> has no non-generic counterpart.
Class
Provides a base class for implementations of the IComparer generic interface.
Represents a collection of keys and values.
Represents the collection of keys in a Dictionary. This class cannot be inherited.
Represents the collection of values in a Dictionary. This class cannot be inherited.
Provides a base class for implementations of the IEqualityComparer generic interface.
The exception that is thrown when the key specified for accessing an element in a collection does not match any key in the collection.
Represents a doubly linked list.
Represents a node in a LinkedList. This class cannot be inherited.
Represents a strongly typed list of objects that can be accessed by index. Provides methods to search, sort, and manipulate lists.
Represents a first-in, first-out collection of objects.
Represents a collection of key/value pairs that are sorted on the key.
Represents the collection of keys in a SortedDictionary. This class cannot be inherited.
Represents the collection of values in a SortedDictionary. This class cannot be inherited
Represents a collection of key/value pairs that are sorted by key based on the associated IComparer implementation.
Represents a variable size last-in-first-out (LIFO) collection of instances of the same arbitrary type.
Description
Defines methods to manipulate generic collections.
Defines a method that a type implements to compare two objects.
Represents a generic collection of key/value pairs.
Exposes the enumerator, which supports a simple iteration over a collection of a specified type.
Supports a simple iteration over a generic collection.
Defines methods to support the comparison of objects for equality.
Represents a collection of objects that can be individually accessed by index.
Description
Enumerates the elements of a Dictionary.
Enumerates the elements of a Dictionary.KeyCollection.
Enumerates the elements of a Dictionary.ValueCollection.
Defines a key/value pair that can be set or retrieved.
Enumerates the elements of a LinkedList.
Enumerates the elements of a List.
Enumerates the elements of a Queue.
Enumerates the elements of a SortedDictionary.
Enumerates the elements of a SortedDictionary.KeyCollection.
Enumerates the elements of a SortedDictionary.ValueCollection.
Enumerates the elements of a Stack.
Tags
There are three ways you can specify a Try/Catch/Finally block:
Try/Catch
Try/Finally
Try/Catch/Finally
1: int[] array1={0,0};
2: int[] array2={0,0};
3:
4: try
5: {
6: Array.Copy(array1,array2,-1);
7: }
8: catch (ArgumentOutOfRangeException e)
9: {
10: Console.WriteLine("Error: {0}", e);
11: }
12: finally
13: {
14: Console.WriteLine("This statement is always executed.");
15: }
A catch handler that only catches System.Exception or System.SystemException is called a general catch handler and should be avoided whenever possible as it can hide run-time problems and complicate debugging.
Since all exceptions in .NET inherit from System.Exception, this type of catch block will always match for any exception. If you think of catch blocks being evaluated in a "top down" approach, the first catch block that matches will be the one used. This means that if you put a general catch block first, none of the other catch blocks will be evaluated.
The using Statement (C#) allows programmers to specify when an object (or objects) that use resources should release them. The object provided to the using statement must implement the IDisposable Interface (System)
. A using statement is exited when the end of the statement is reached or an exception is thrown and control leaves the statement block early. This is a compile time "translation" that occurs where the compiler actually translates this to a try/finally block.
The using statement can be declared in different ways:
1: // Object declared in the using statement
2: using (Font font1 = new Font("Arial", 10.0f))
3: {
4: }
5:
6: // Object declared outside (before) the using statement
7: Font font2 = new Font("Arial", 10.0f);
8: using (font2)
9: {
10: }
11:
12: // Multiple objects (must be declared inside the using statement, and must
13: // all be of the same type)
14: using (Font font3 = new Font("Arial", 10.0f), font4 = new Font("Arial", 10.0f))
15: {
16: }
The using Directive (C#) actually has two uses:
To allow the use of types in a namespace without needing to fully qualify that type.
To create an alias for a namespace or a type.
http://www.codeproject.com/useritems/NDestructors.asp
http://msdn2.microsoft.com/en-us/library/b1yfkh5e(vs.80).aspx
http://msdn2.microsoft.com/en-us/library/fs2xkftw(VS.80).aspx
Class instances often encapsulate control over resources that are not managed by the runtime, such as window handles (HWND), database connections, and so on. Therefore, you should provide both an explicit and an implicit way to free those resources. Provide implicit control by implementing the protected Finalize Method on an object (destructor syntax in C# and C++). The garbage collector calls this method at some point after there are no longer any valid references to the object.
In some cases, you might want to provide programmers using an object with the ability to explicitly release these external resources before the garbage collector frees the object. If an external resource is scarce or expensive, better performance can be achieved if the programmer explicitly releases resources when they are no longer being used. To provide explicit control, implement the Dispose Method provided by the IDisposable Interface. The consumer of the object should call this method when it is finished using the object. Dispose can be called even if other references to the object are alive.
Note that even when you provide explicit control using Dispose, you should provide implicit cleanup using the Finalize method. Finalize provides a backup to prevent resources from permanently leaking if the programmer fails to call Dispose.
For more information about implementing Finalize and Dispose to clean up unmanaged resources, see Garbage Collection.
Empty String
Checking if a string is empty or not is a basic programming need. The effective way to check if a string is empty or not is to use the Length property of the string class, instead of using null or comparing with " " string.
string str1 = AMethodReturnsString()
{
// Do something and return a string
}
if (str1.Length >0 )
{
// do something
}
String Concatenation
Whenever you modify a String it returns a new string as the result. Creating many String objects might degrade the performance of your program. You can avoid creating a new instance of String by using the StringBuilder class.
Say you want to concatenate two strings. Here is the traditional way -
string str1 = "I like ";
string str2 = "Soccer";
string strConcat = string.Concat(str1, str2);
The value of strConcat = "I like Soccer". You can use the StringBuilder class and its Append method to do the same.
StringBuilder MyStrBuilder = new StringBuilder ("I like ");
String newStr = "Soccer";
MyStrBuilder.Append(newStr);
The value of MyStrBuilder is "I like Soccer".
Comparing String
Use string.Equals method to compare two strings.
string str1 = AMethodReturnsString()
if (str1.Equals("TestSting") )
{
// do something
yield keyword is used to return items from a loop within a method and retain the state of the method through multiple calls. That is a bit hard to wrap your head around, so as always, an example will help;
public static IEnumerable<int> Range( int min, int max )
{
for ( int i = min; i < max; i++ )
{
yield return i;
}
}
Each time Range is called, it will return one value in the given range. Of interest is that it maintains the state between calls. The best way to think of it is that for the first call to the method, execution starts at the first line and continues until it hits a yield statement at which time it returns the value. The subsequent runs through the method continue execution at the statement after the yield, continuing to yield values or exiting at the end of the method.
Using this, you can write the following code;
foreach ( int i in Range( 10, 20 ) )
{
Console.Write( i.ToString() + ” “ );
}
Which will return the following;
10 11 12 13 14 15 16 17 18 19
Why bother you say? Why not just iterate through the numbers yourself? The answer lies in the fact that each call maintains state, so you don’t have to. The above example doesn’t really show you the power, so let’s try a more complex example, calculating prime numbers.
public static IEnumerable<int> Primes( int max )
{
yield return 2;
List<int> found = new List<int>();
found.Add( 3 );
int candidate = 3;
while ( candidate <= max )
{
bool isPrime = true;
foreach ( int prime in found )
{
if ( prime * prime > candidate )
{
break;
}
if ( candidate % prime == 0 )
{
isPrime = false;
break;
}
}
if ( isPrime )
{
found.Add( candidate );
yield return candidate;
}
candidate += 2;
}
}
Notice that there are multiple yields within this method and that the state is maintained through each call. You can now print out all of the prime numbers below 50 with;
foreach ( int prime in Primes( 50 ) )
{
Console.Write( prime.ToString() + ” “ );
}
There is also the yield break statement. If a yield break statement is hit within a method, execution of that method stops with no return. Using this, the first method could be rewritten like this;
public static IEnumerable<int> Range( int min, int max )
{
while ( true )
{
if ( min >= max )
{
yield break;
}
yield return min++;
}
}
It is not as useful in this case, but I’ll leave it to you to find more interesting reasons to break out of a loop. Also, even though I used the generic IEnumerable<T> for all of my examples, you can also use IEnumerable.
One key point to add is that execution of yield methods are deferred: they aren’t evaluated until you foreach over them. Thus, the following code, even though it looks like an infinite loop, is perfectly fine:
while(true)
{
yield return 1;
}
It will simply keep yielding 1 until you stop foreach-ing over it.
Another point to consider is that since yield methods are delay-executed, any argument validation won’t get applied until you foreach over it. For example,
IEnumerable GetEvens(IEnumerable input)
{
if (input == null ) throw new ArgumentNullException();
…
yield return …;
}
Calling that method like this:
IEnumerable evens = GetEvents(null);
It won’t result in an exception! Not until you foreach over evens.
For this reason, argument validation should be done first, then return the result of another method that does the actual yielding.
System.Diagnostic namespace contains the tracing API's that are thread-safe, have configurable levels of tracing, zero-foot print with conditional compilation, trace listener support, etc...
In .NET the System.Diagnostics.ConditionalAttribute can be used for conditional compilation. A method can be marked with this attribute as follows
using System.Diagnostics;
static class Logger
{
[Conditional("TRACE")]
static public void Info(string message)
{
Console.WriteLine(message);
}
}
This means that the Logger.Trace is compiled into IL only when the TRACE sumbol is defined either in
the command line build as /define:TRACE or in the VS IDE in Project->Properties->Build->General->Conditional Compilation symbols. This makes ConditionalAttribute an excellent choice for logger and debug utilities. For example the logger can have the Info and verbose methods marked with [Conditional("Debug")] and hence they do not add to the burden of in release bits. Conditional attributes is a much better choice than #ifdefs as they are always syntax verified.
However, it brought up a very interesting discussion recently. Consider the following code
MyClass mc = new MyClass();
Logger.Info(mc.ToString());
The question is does the mc.ToString evaluate when TRACE is not defined?? Or in other words are
parameters of conditionally compiled methods evaluated? If it does then even for release bits overhead starts creeping in. The good news is that it doesn't. An easy way to verify is to override MyClass::ToString and put in a Console.WriteLine into it. This method will not be called if TRACE is not defined. Or you can just use ILDASM or .NET Reflector to see that the method call doesn't even go into the IL and hence there can be no overhead.
http://www.jakevoytko.com/blog/2008/09/01/the-law-of-expanding-wrappers/
1. Write Singleton class
2. BeginInvoke
3. how to update UI from the thread ?
4 . What is GAC ?
Each computer wherein the common language runtime is installed has a machine-wide code cache called the Global Assembly Cache. This Global Assembly Cache stores .NET assemblies specifically designated to be shared by several applications on that computer.
5. Security
6. When we need rewrite GetHash..() in System.Object
7. Difference between Ancor and Docing in Windows Forms
8. Difference between MenuToolbarStrip and ... components
9. Why there are attributes in C#, but not in C++ ?
10. Describe serialization options in C#
Describe the difference between a Thread and a Process?
What is a Windows Service and how does its lifecycle differ from a "standard" EXE?
What is the maximum amount of memory any single process on Windows can address? Is this different than the maximum virtual memory for the system? How would this affect a system design?
What is the difference between an EXE and a DLL?
What is strong-typing versus weak-typing? Which is preferred? Why?
Corillian's product is a "Component Container." Name at least 3 component containers that ship now with the Windows Server Family.
What is a PID? How is it useful when troubleshooting a system?
How many processes can listen on a single TCP/IP port?
What is the GAC? What problem does it solve?
Mid-Level .NET Developer
Describe the difference between Interface-oriented, Object-oriented and Aspect-oriented programming.
Describe what an Interface is and how it’s different from a Class.
What is Reflection?
What is the difference between XML Web Services using ASMX and .NET Remoting using SOAP?
Are the type system represented by XmlSchema and the CLS isomorphic?
Conceptually, what is the difference between early-binding and late-binding?
Is using Assembly.Load a static reference or dynamic reference?
When would using Assembly.LoadFrom or Assembly.LoadFile be appropriate?
What is an Asssembly Qualified Name? Is it a filename? How is it different?
Is this valid? Assembly.Load("foo.dll");
How is a strongly-named assembly different from one that isn’t strongly-named?
Can DateTimes be null?
What is the JIT? What is NGEN? What are limitations and benefits of each?
How does the generational garbage collector in the .NET CLR manage object lifetime? What is non-deterministic finalization?
What is the difference between Finalize() and Dispose()?
How is the using() pattern useful? What is IDisposable? How does it support deterministic finalization?
What does this useful command line do? tasklist /m "mscor*"
What is the difference between in-proc and out-of-proc?
What technology enables out-of-proc communication in .NET?
When you’re running a component within ASP.NET, what process is it running within on Windows XP? Windows 2000? Windows 2003?
Senior Developers/Architects
What’s wrong with a line like this? DateTime.Parse(myString);
What are PDBs? Where must they be located for debugging to work?
What is cyclomatic complexity and why is it important?
Write a standard lock() plus “double check” to create a critical section around a variable access.
What is FullTrust? Do GAC’ed assemblies have FullTrust?
What benefit does your code receive if you decorate it with attributes demanding specific Security permissions?
What does this do? gacutil /l | find /i "Corillian"
What does this do? sn -t foo.dll
What ports must be open for DCOM over a firewall? What is the purpose of Port 135?
Contrast OOP and SOA. What are tenets of each?
How does the XmlSerializer work? What ACL permissions does a process using it require?
Why is catch(Exception) almost always a bad idea?
What is the difference between Debug.Write and Trace.Write? When should each be used?
What is the difference between a Debug and Release build? Is there a significant speed difference? Why or why not?
Does JITting occur per-assembly or per-method? How does this affect the working set?
Contrast the use of an abstract base class against an interface?
What is the difference between a.Equals(b) and a == b?
In the context of a comparison, what is object identity versus object equivalence?
How would one do a deep copy in .NET?
Explain current thinking around IClonable.
What is boxing?
Is string a value type or a reference type?
What is the significance of the "PropertySpecified" pattern used by the XmlSerializer? What problem does it attempt to solve?
Why are out parameters a bad idea in .NET? Are they?
Can attributes be placed on specific parameters to a method? Why is this useful?
C# Component Developers
Juxtapose the use of override with new. What is shadowing?
Explain the use of virtual, sealed, override, and abstract.
Explain the importance and use of each component of this string: Foo.Bar, Version=2.0.205.0, Culture=neutral, PublicKeyToken=593777ae2d274679d
Explain the differences between public, protected, private and internal.
What benefit do you get from using a Primary Interop Assembly (PIA)?
By what mechanism does NUnit know what methods to test?
What is the difference between: catch(Exception e){throw e;} and catch(Exception e){throw;}
What is the difference between typeof(foo) and myFoo.GetType()?
Explain what’s happening in the first constructor: public class c{ public c(string a) : this() {;}; public c() {;} } How is this construct useful?
What is this? Can this be used within a static method?