What Great .NET Developers Ought To Know (Part one Everyone who writes code)
Scott Hanselman's - What Great .NET Developers Ought To Know is by far the most interesting and challenging .NET interview questions I have seen so far.
Here is my trial.
Part one Everyone who writes code
A process is the smallest unit of isolation available on the Windows operating system before MS .NET era. A process is a container and boundary. A process contains the executable code and data of a program inside memory it has reserved from the operating system. Erroneous code inside of a process cannot corrupt areas outside of the current process.
A thread (of execution) is a series of instructions and a call stack that operate independently of the other threads in a process. A process contains at least one thread executing instructions. For example, in a windows form application there will at least one and the main thread - UI thread. In most cases, there will be multiple threads running asynchronously.
.NET runtime introduces a finer unit over process - AppDomain. An AppDomain belongs to only one single process, but single process can hold multiple AppDomains. Like a process, the AppDomain is both a container and a boundary. The .NET runtime uses an AppDomain as a container for a set of assemblies (code) and data, just like the operating system uses a process as a container for code and data. As the operating system uses a process to isolate misbehaving code, the .NET runtime uses an AppDomain to isolate code inside of a secure boundary.
By default, an assembly is loaded once per AppDomain. Considering case: A process contains multiple AppDomain. Each AppDomain loads an assembly myCommon.dll. The static members and data of myCommon.dll are isolated by the AppDomain boundary. They are not shared at process level.
Some assemblies are expected to be used by several AppDomains, e.g. MSCorLib.dll. They are AppDomain neutral and are loaded to a special loader heap managed by CLR. They cannot be unloaded until the process terminates.
Code in one AppDomain can communicate with types and objects contained in another AppDomain by .NET mechanism such like Remoting. When a thread in one AppDomain calls a method in another AppDomain, the thread transitions between the two AppDomain – the call is synchronous. At any one given time, a thread is considered to be in just one AppDomain.
An AppDomain is relatively cheap to create (compared to a process), and has relatively less overhead to maintain than a process.
Pointers: IIS worker process, Thread Pool,
http://odetocode.com/Articles/305.aspx
Applied Microsoft .NET Framework Programming Designing Microsoft ASP.NET Application
Windows services run as long-running background processes. A Windows service is installed in the registry as an executable object. It is managed by the Service Control Manager (SCM). SCM is a remote procedure call (RPC) server, supports local or remote management of a service. For example, automatically start, stop services while OS starts or stop.
Windows service can be specified to run in the security context of a specific user account that’s different from the logged on user or the default system account. Therefore, a Windows service can be started before a user logs on and continue to run even after the user logs off.
As Windows services running as background processes, all events or dialogs raises are not visible to users. They are all written to system EventLog.
A ‘standard’ exe is executed by current logged on user and by default runs in the current user’s security context. It runs at the ‘foreground’ as application. It interacts with user directly. It stops when the execution completed or is stopped by the user or when user logs off.
A single process on X86 windows can normally address 2GB memory (the virtual address space, regardless of the amount of physical memory that is actually available). Although Windows 2003 enable 3GB virtual address space. The maximum virtual memory for a 32-bit system is 4GB, 2GB of it is allocated to Kernel.
This affects system design when designing for memory intensive applications such as databases, enterprise applications etc...
Pointers: Managing Virtual Memory in Win32
DLL, or Dynamic Link Library (binary files) provides a library of functions to application (EXE) at run time. DLLs are linked to an application when it is loaded and executed at run time rather than when it is linked (at compilation time with the referencing application). When an application (EXE) uses a DLL, the operating system loads the DLL into memory, resolves references to functions in the DLL so that it can be called by the application, and unloads the DLL when it is no longer needed.
The main difference is a DLL is in-process, meaning it runs within the callee/client process An EXE is out-of-process, meaning runs within its own process.
Pointers: Security context, threading model
In a weakly typed language, the type of a value depends on how it is used. For example if I can pass a string to the addition operator and it will be interpreted as a number or cause an error if the contents of the string cannot be translated into a number. Similarly, I can concatenate strings and numbers or use strings as booleans, etc. And complier (if compiling required) would not found the mis-type conversion.
In a strongly typed language, a value has a type and that type cannot change. What you can do to a value depends on the type of the value. Mis-type conversion will be caught by compliers. With model IDE, such like Visual Studio 2003 and add-ins like Resharper, the issue is reported simultaneously as typing, even before hitting ‘build’ button.
The advantage of a strongly typed language is that you are forced to make the behaviour of your program explicit. If you want to add a number and a string your code must translate the string into a number to be used as an operand of the addition operator. This makes code easier to understand because there is no (or less) hidden behaviour. However, it also makes your code more verbose.
The advantage of a weakly typed language is that you need to write less code. However, that code is harder to understand because a lot of its behaviour is hidden in implicit type conversions.
(Cited from http://c2.com/cgi/wiki?WeakAndStrongTyping)
From a more practical point of view I reckon strong-type and weak-type are mainly for the developer’s benefit on code self-documentation. Because though in weak-type language implementations, type conversion problem will only surface at run time. You certainly will unit test every corner before release it. In fact you should write your test cases before writing codes (What? Do you say you can’t do Test Driven Development for scripting languages?)
System.Web.UI.Page, System.Windows.Forms.Form and System.ComponentModel.Container
The essence of component development is not to build what you can buy. Buy a rich text web control from the market for $99 instead of design and implement one from scratch. Snapping together pre-tested components are faster, cheaper and probably more reliable than coding everything for yourself.
What is a '.NET component'? Arguably, almost any .NET class file is a component, in that it can easily be compiled to a DLL, it benefits from .NET versioning, and it can be reused. If you narrow the definition to components that are 'designable', in other words you can drop instances onto a Visual Studio .NET design surface and set their properties or create event handlers visually, then you need a class that directly or indirectly implements IComponent. Designable objects do not necessarily have a user interface. Those that do are controls as well as components, and inherit from System.Windows.Forms.Control or System.Web.UI.Control.
The existence of components also implies the existence of containers, which again may be visual or non-visual. In the .NET Framework both ASP.NET Web Forms and rich client Windows Forms are visual component containers. The container plays an important role in component management. In particular, all containers implement IDisposable, which means they have a Dispose method for releasing unmanaged resources such as window handles or open files. In their Dispose method, containers must also call Dispose on all the components they host.
PID stands for Process Identifier, a uniquely assigned integer that identifies a process in the operating system. In any system, applications use PID to identify the process uniquely. Also, it is used in diagnosing the problems with the process in Multi-Tasking systems.
As many as you like? But do it this way is strange. You probably will only want one process listening to a TCP/IP port, so it can handle the data solely.
What is the GAC? What problem does it solve?
Global Assembly Cache. It is a machine-wide code cache. Assemblies deployed in the global assembly cache must have a strong name. GAC solves the problems of versioning, DLL hell etc.