C#.Net Interview Questions
C#.Net Interview Questions
0 Interview Questions
CLR Basics
CLR’s execution model
Shared assemblies and strong named assemblies
Designing Types
Type and member basics
Constants and Fields
Methods: Constructors, Operators
Events
Essential Types
Array
Strings
Delegates
Interface
Generics
Collections
Attributes
Reflection
CLR facilities
Exceptions
Automatic Memory Management
CLR Hosting and Appdomains
Threading
CLR Basics
CLR’s execution model
Page 1 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Page 2 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
What is the common language runtime (CLR)? What are it’s features?
The common language runtime is the execution engine for .NET Framework
applications. The CLR allows programmers to ignore many details of the specific CPU
that will execute the program. It also provides other important services, including the
following:
Memory management
Thread management
Exception handling
Garbage collection
Security
Page 3 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Compiling translates your source code into MSIL and generates the required
metadata.
3. Compiling MSIL to native code.
At execution time, a just-in-time (JIT) compiler translates the MSIL into native
code. During this compilation, code must pass a verification process that
examines the MSIL and metadata to find out whether the code can be
determined to be type safe. Alternatively, the CIL code can be compiled to
native code in a separate step prior to runtime by using the Native Image
Generator (NGEN). This speeds up all later runs of the software as the CIL-to-
native compilation is no longer necessary.
4. Running code.
The common language runtime provides the infrastructure that enables
execution to take place as well as a variety of services that can be used during
execution.
The CLR (Common Language Runtime) is Microsoft's primary implementation of the CLI.
Microsoft also has a shared source implementation known as ROTOR, for educational
purposes, as well as the .NET Compact Framework for mobile devices. Non-Microsoft
CLI implementations include Mono and DotGNU [Link].
Page 4 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
The common type system is a rich type system, built into the common language
runtime, that supports the types and operations found in most programming
languages. The common type system supports the complete implementation of a wide
range of programming languages.
The Common Language Specification is a set of constructs and constraints that serves
as a guide for library writers and compiler writers. It allows libraries to be fully usable
from any language supporting the CLS, and for those languages to integrate with each
other. The Common Language Specification is a subset of the common type system.
The Common Language Specification is also important to application developers who
are writing code that will be used by other developers. When developers design
publicly accessible APIs following the rules of the CLS, those APIs are easily used from
all other programming languages that target the common language runtime.
Page 5 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Figure 1-6 Languages offer a subset of the CLR/CTS and a superset of the CLS (but not neces-
sarily the same superset)
Combined with metadata and the common type system, MSIL allows for true cross-
language integration.
Closely related to managed code is managed data—data that is allocated and de-
allocated by the common language runtime's garbage collector. C#, Visual Basic, and
JScript .NET data is managed by default. C# data can, however, be marked as
unmanaged through the use of special keywords. Visual Studio .NET C++ data is
unmanaged by default (even when using the /CLR switch), but when using Managed
Extensions for C++, a class can be marked as managed by using the __gc keyword. As
the name suggests, this means that the memory for instances of the class is managed
by the garbage collector. In addition, the class becomes a full participating member of
the .NET Framework community, with the benefits and restrictions that brings. An
example of a benefit is proper interoperability with classes written in other languages
(for example, a managed C++ class can inherit from a Visual Basic class). An example
of a restriction is that a managed class can only inherit from one base class.
What is JIT?
Page 6 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
JIT is a compiler that converts MSIL to native code. The native code consists of
hardware specific instructions that can be executed by the CPU.
Rather than converting the entire MSIL (in a portable executable [PE] file) to native
code, the JIT converts the MSIL as it is needed during execution. This converted native
code is stored so that it is accessible for subsequent calls.
Assembly
What is an assembly?
An assembly is the primary building block of a .NET Framework application. It is a
collection of functionality that is built, versioned, and deployed as a single
implementation unit (as one or more files). All managed types and resources are
marked either as accessible only within their implementation unit, or as accessible by
code outside that unit.
Establishes the assembly identity (in the form of a text name), version, culture,
and digital signature (if the assembly is to be shared across applications).
Defines what files (by name and file hash) make up the assembly
implementation.
Specifies the types and resources that make up the assembly, including which
are exported from the assembly.
Itemizes the compile-time dependencies on other assemblies.
Specifies the set of permissions required for the assembly to run properly.
This information is used at run time to resolve references, enforce version binding
policy, and validate the integrity of loaded assemblies. The runtime can determine and
locate the assembly for any running object, since every type is loaded in the context of
an assembly. Assemblies are also the unit at which code access security permissions
are applied. The identity evidence for each assembly is considered separately when
determining what permissions to grant the code it contains.
Page 7 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
The self-describing nature of assemblies also helps makes zero-impact install and
XCOPY deployment feasible.
Assemblies can be static or dynamic. Static assemblies can include .NET Framework
types (interfaces and classes), as well as resources for the assembly (bitmaps, JPEG
files, resource files, and so on). Static assemblies are stored on disk in portable
executable (PE) files. You can also use the .NET Framework to create dynamic
assemblies, which are run directly from memory and are not saved to disk before
execution. You can save dynamic assemblies to disk after they have executed.
There are several ways to create assemblies. You can use development tools, such as
Visual Studio 2005, that you have used in the past to create .dll or .exe files. You can
use tools provided in the Windows Software Development Kit (SDK) to create
assemblies with modules created in other development environments. You can also
use common language runtime APIs, such as [Link], to create dynamic
assemblies.
There are several ways to group these elements in an assembly. You can group all
elements in a single physical file, which is shown in the following illustration.
Single-file assembly
Alternatively, the elements of an assembly can be contained in several files. These files
can be modules of compiled code (.netmodule), resources (such as .bmp or .jpg files),
or other files required by the application. Create a multifile assembly when you want to
combine modules written in different languages and to optimize downloading an
application by putting seldom used types in a module that is downloaded only when
needed.
Page 8 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Multifile assembly
Note
The files that make up a multifile assembly are not physically linked by the file
system. Rather, they are linked through the assembly manifest and the common
language runtime manages them as a unit.
In this illustration, all three files belong to an assembly, as described in the assembly
manifest contained in [Link]. To the file system, they are three separate files.
Note that the file [Link] was compiled as a module because it contains no
assembly information. When the assembly was created, the assembly manifest was
added to [Link], indicating its relationship with [Link] and
[Link].
As you currently design your source code, you make explicit decisions about how to
partition the functionality of your application into one or more files. When
designing .NET Framework code, you will make similar decisions about how to partition
the functionality into one or more assemblies.
There are several reasons you may elect to build and use shared assemblies, such as
the ability to express version policy. The fact that shared assemblies have a
cryptographically strong name means that only the author of the assembly has the key
Page 9 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
to produce a new version of that assembly. Thus, if you make a policy statement that
says you want to accept a new version of an assembly, you can have some confidence
that version updates will be controlled and verified by the author. Otherwise, you don't
have to accept them.
For locally installed applications, a shared assembly is typically explicitly installed into
the global assembly cache (a local cache of assemblies maintained by the .NET
Framework). Key to the version management features of the .NET Framework is that
downloaded code does not affect the execution of locally installed applications.
Downloaded code is put in a special download cache and is not globally available on
the machine even if some of the downloaded components are built as shared
assemblies.
The classes that ship with the .NET Framework are all built as shared assemblies.
Strong name signing does not involve certificates like Authenticode does. There are no
third party organizations involved, no fees to pay, and no certificate chains. In addition,
the overhead for verifying a strong name is much less than it is for Authenticode.
However, strong names do not make any statements about trusting a particular
publisher. Strong names allow you to ensure that the contents of a given assembly
haven't been tampered with, and that the assembly loaded on your behalf at run time
comes from the same publisher as the one you developed against. But it makes no
statement about whether you can trust the identity of that publisher.
A namespace is a logical naming scheme for types in which a simple type name, such
as MyType, is preceded with a dot-separated hierarchical name. Such a naming
scheme is completely under the control of the developer. For example, types
[Link].A and [Link].B might be logically expected to
have functionality related to file access. The .NET Framework uses a hierarchical
naming scheme for grouping types into logical categories of related functionality, such
as the Microsoft® [Link] application framework, or remoting functionality. Design
tools can make use of namespaces to make it easier for developers to browse and
reference types in their code. The concept of a namespace is not related to that of an
assembly. A single assembly may contain types whose hierarchical names have
different namespace roots, and a logical namespace root may span multiple
assemblies. In the .NET Framework, a namespace is a logical design-time naming
convenience, whereas an assembly establishes the name scope for types at run time.
Page 10 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Note: DotNet does not considers whether the .dll is available in the release folder or
not.
Incase release folder is not available then the .dll will refer the debug folder.
If the reference file is selected explicitly to point debug or release the selected folder is
referenced.
What is GAC? What are the steps to create an assembly and add it to the
GAC?
The global assembly cache (GAC) is a machine-wide code cache (a place holder or
container) that stores assemblies specifically designated to be shared by several
applications on the computer. You should share assemblies by installing them into the
global assembly cache only when you need to.
Steps:
- Create a strong name using [Link] tool eg: sn -k [Link]
- in [Link], add the strong name eg:
[assembly:assemblyKeyFile("[Link]")]
- recompile project, and then install it to GAC in two ways :
· drag & drop it to assembly folder (C:\WINDOWS\assembly OR C:\WINNT\
assembly) ([Link] tool)
· gacutil -i [Link]
Can I delete the source file which I have used to register in GAC?
Yes, the assembly makes a copy in the GAC folder. So the source file can be deleted.
The following command removes the assembly hello from the global assembly cache
(GAC) as long as no reference counts exist for the assembly.
gacutil /u hello
Page 11 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Note : If there is only one version of hello assembly the above command is fine and you
are in safer side. Incase if there are more than one version of the assembly or different
assembly with same name exists then the above command might remove more than
one assembly from the assembly cache because the assembly name is not fully
specified. For example, if both version [Link] and [Link] of hello are installed in the
cache, the command gacutil /u hello removes both of the assemblies.
Then how to remove the assembly safely: Use the following example to avoid removing
more than one assembly. This command removes only the hello assembly that
matches the fully specified version number, culture, and public key.
gacutil /u hello, Version=[Link], Culture="de", PublicKeyToken=45e343aae32233ca
The .NET Framework uses assemblies as the fundamental unit for several purposes:
· Security
· Type Identity
· Reference Scope
· Versioning
· Deployment
What is Versioning?
Each assembly has a 128-bit version number that is presented as a set of four decimal
pieces: [Link]
By default, an assembly will only use types from the exact same assembly (name and
version number) that it was built and tested with. That is, if you have an assembly that
uses a type from version [Link] of another assembly, it will (by default) not use the
same type from version [Link] of the other assembly. This use of both name and
version to identify referenced assemblies helps avoid the "DLL Hell" problem of
upgrades to one application breaking other applications.
Tip An administrator or developer can use configuration files to relax this strict
version checking. Look for information on publisher policy in the .NET Framework
Developer's Guide.
Yes, assembly can have more that one file. Each file can be developed from different
language too. Using the [Link] utility all the required files are grouped and made into
single file.
Page 12 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
When deciding what to include in your assembly, keep in mind how you intend to
manage these in the future, and how you want applications to use them. For example,
if you include two files in an assembly, each time you ship a new version of the
assembly, you would include both files, whether or not both have changed. If you have
two files with a strong interdependency, and you decide to ship as separate
assemblies, you need to be aware that customers have a choice of mixing versions. If
you update both assemblies, a customer may choose to use the new version of one
and the older version of the other, which may or may not be compatible
Referring, project itself is right and advantages, for the following reasons:
They automatically track project configuration changes. For example, when you build
using a debug configuration, any project references refer to debug assemblies
generated by the referenced projects, while they refer to release assemblies in a
release configuration. This means that you can automatically switch from debug to
release builds across projects without having to reset references.
Private assemblies are deployed within the directory structure of the application in
which they are used. Private assemblies can be placed directly in the application
directory, or in a subdirectory thereof. The CLR finds these assemblies through a
process called probing. Probing is simply a mapping of the assembly name to the name
of the file that contains the manifest.
If the same assembly is used by two app, what will be stored in GAC and how
it is stored?
In GAC, only one master copy of the dll is stored. But if another application is installing
the same assembly (with the same version) a reference with a native image is created.
So if we have a dll, which is used by three applications, there will be one master and
two images in the GAC.
You can see this when you check the GAC folder. In COM you can't have same dlls with
different versions.
What do you call as DLL Hell in COM and how was that fixed in .Net?
Let’s consider a shared dll used by msn messenger and your own application. When
you upgrade MSN Messenger, a new version of shared dll will be installed which may
Page 13 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
not be compatible with your application, which leads in failure of your application. This
scenario is described as DLL Hell.
In .Net the problem is fixed using GAC - shared assembly, where you can have more
than one version of the same dll. If new version of msn is installed, the new version of
the dll in installed in GAC with the new version number. The important thing in GAC is
that, more than one version of same dll can co-exist, so older version of dll, which is
referenced by your application, will not get affected.
How to override the assembly name and version combination key while
selecting and using the assembly in the GAC?
The assembly is selected by name and the version from the GAC, sometimes we
require our application to use another version of the same assembly. For example
An administrator may deploy a critical bug fix to a shared assembly and want all
applications to use this new version regardless of which version they were built with.
Also, the vendor of a shared assembly may have shipped a service release to an
existing assembly and would like all applications to begin using the service release
instead of the original version. These scenarios and others are supported in the .NET
Framework through version policies.
Version policies are stated in XML files and are simply a request to load one version of
assembly instead of another. For example, the following version policy directs the CLR
to load version [Link] instead of version [Link] of an assembly called MarineCtrl:
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MarineCtrl" publicKeyToken="9335a2124541cfb9" />
<bindingRedirect oldVersion="[Link]" NewVersion="[Link]" />
</dependentAssembly>
</assemblyBinding>
In addition to redirecting from a specific version number to another, you can also
redirect from a range of versions to another version. For example, the following policy
redirects all versions from [Link] through [Link] of MarineCtrl to version [Link]:
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MarineCtrl" publicKeyToken="9335a2124541cfb9" />
<bindingRedirect oldVersion="[Link]-[Link]" newVersion="[Link]" />
</dependentAssembly>
</assemblyBinding>
Application-specific Policy. Each application has an optional configuration file that can
specify the application’s desire to bind to a different version of a dependent assembly.
The name of the configuration file varies based on the application type. For executable
files, the name of the configuration file is the name of the executable plus a ".config"
extension. For example, the configuration file for "[Link]" would be
Page 14 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Machine-wide Policy. The final policy level is machine-wide policy (sometimes referred
to as Administrator policy). Machine-wide policy is stored in [Link] which is
located in the "config" subdirectory under the .NET Framework install directory. The
install directory is %windir%\[Link]\framework\%runtimeversion%. Policy
statements made in [Link] affect all applications running on the machine.
Machine-wide policy is used by Administrators to force all applications on a given
machine to use a particular version of an assembly. The most common scenario in
which this is used is when a security or other critical bug fix has been deployed to the
global assembly cache. After deploying the fixed assembly, the Administrator would
use machine-wide version policy to ensure that applications don’t use the old, broken
version of the assembly.
A native image is a file containing compiled processor-specific machine code. Note that
the native image that [Link] generates cannot be shared across Application
Domains. Therefore, you cannot use [Link] in application scenarios, such as
[Link], that require assemblies to be shared across application domains.
Pre-compiling assemblies with [Link] can improve the startup time for applications,
because much of the work required to execute code has been done in advance.
Therefore, it is more appropriate to use [Link] for client-side applications where you
have determined that the CPU cycles consumed by JIT compilation cause slower
performance.
Page 15 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Yes, the size of the GAC can be modified as per the requirements. To set the size,
browse through the gac folder %windir%\Assembly\ in windows explorer.
Select ToolsàCache Options from the menu to set the maximum size of the disk space
to be allotted for GAC.
To view the physical file structure add a binary value named 'DisableCacheViewer' to
the registry key HKLM\Software\Microsoft\Fusion and set it to a non-zero value.
Assembly versioning allows the application to specify not only the library it needs to
run (which was available under Win32), but also the version of the assembly.
Supporting .Net, because DLL made in C#.Net semi compiled version. It’s not a com
object. It is used only in .Net Framework As it is to be compiled at runtime to byte
code.
Page 16 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="ClassLibraryVersion"
publicKeyToken="b035c4774706cc72" culture="neutral" />
<bindingRedirect oldVersion= "1.1.2" newVersion= "1.1.1"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
The .NET Framework simplifies deployment by making zero-impact install and XCOPY
deployment of applications feasible. Because all requests are resolved first to the
Page 17 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
private application directory, simply copying an application's directory files to disk is all
that is needed to run the application. No registration is required.
This scenario is particularly compelling for Web applications, Web Services, and self-
contained desktop applications. However, there are scenarios where XCOPY is not
sufficient as a distribution mechanism. An example is when the application has little
private code and relies on the availability of shared assemblies, or when the
application is not locally installed (but rather downloaded on demand). For these cases,
the .NET Framework provides extensive code download services and integration with
the Windows Installer. The code download support provided by the .NET Framework
offers several advantages over current platforms, including incremental download,
code access security (no more Authenticode dialogs), and application isolation (code
downloaded on behalf of one application doesn't affect other applications). The
Windows Installer is another powerful deployment mechanism available to .NET
applications. All of the features of Windows Installer, including publishing,
advertisement, and application repair will be available to .NET applications in Windows
Installer 2.0.
I've written an assembly that I want to use in more than one application.
Where do I deploy it?
Assemblies that are to be used by multiple applications (for example, shared
assemblies) are deployed to the global assembly cache. In the prerelease and Beta
builds, use the /i option to the GACUtil SDK tool to install an assembly into the cache:
gacutil /i [Link]
Windows Installer 2.0, which ships with Windows XP and Visual Studio .NET will be able
to install assemblies into the global assembly cache.
How can I see what assemblies are installed in the global assembly cache?
The .NET Framework ships with a Windows shell extension for viewing the assembly
cache. Navigating to % windir%\assembly with the Windows Explorer activates the
viewer.
How can I make sure my C# classes will interoperate with other .Net
languages?
Make sure your C# code conforms to the Common Language Subset (CLS). To help
with this, add the [assembly: CLSCompliant (true)] global attribute to your C# source
files. The compiler will emit an error if you use a C# feature which is not CLS-
compliant.
Not exactly. The .NET Framework has a comprehensive class library, which C# can
make use of. C# does not have its own class library.
Page 18 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
What are the differences between .NET dll and .NET exe?
.Exe
1. These are outbound file.
2. Only one .exe file exists per application.
3. Exe cannot be shared with other applications.
4. exe is an executable [Link] runs on its own
5. Exe has main Entry point available
.dll
1. These are inbund file .
2. Many .dll files may exists in one application.
3. dll can be shared with other applications.
4. dll is a dynamic link library located at run time using PATH env variable. It is linked
or referenced to the exe at run time
5. There is no any entry point available in a dll.
"First we need to be clear that both "exe" and "dll" are fundamentally the same but the
difference lies in how windows interacts with them."
When windows loads a dll, it runs the initialization code and then leaves it alone.
Functions in the dll are called if they are explicitly referenced by an application.
Another thing, when dll gets crashed it not only crashes itself but also the application
as the dll runs in the memory of the parent application.
When windows load an exe, the exe's initialization code is responsible for creating what
is called as "message pump", nothing but a program loop which runs as long as the
application is running. The message pump request messages from the operating
system. Windows keep track of the application as a separate task. It allocates separate
memory for both the exe and the application using that exe. The memory area in which
each exe runs is called "Process Space".
*******************************************************************
Working with Types
Type Fundamentals
Primitive, Reference and Value Types
Page 19 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Type Fundamentals
What is the use/advantage of Object class?
It supports all classes in the .NET Framework class hierarchy and provides low-level
services to derived classes. This is the ultimate base class of all classes in the .NET
Framework; it is the root of the type hierarchy.
Namespace: System
Assembly: mscorlib (in [Link])
Languages typically do not require a class to declare inheritance from Object because
the inheritance is implicit. Reference types inherit the object class either directly or
through other reference types. Value types inherit implicitly from the object class
through [Link].
Page 20 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Name Description
Public Methods
Name Description
ReferenceEquals Determines whether the specified Object instances are the same
instance.
Protected Methods
Name Description
Finalize Allows an Object to attempt to free resources and perform other cleanup
operations before the Object is reclaimed by garbage collection.
using System;
Page 21 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Page 22 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
s1 and s2 are different objects (hence == returns false), but they are equivalent
(hence Equals() returns true).Unfortunately there are exceptions to these rules. The
implementation of Equals() in [Link] (the one you'll inherit by default if you
write a class) compares identity, i.e. it's the same as operator ==. So Equals() only
tests for equivalence if the class author overrides the method (and implements it
correctly). Another exception is the string class - its operator == compares value
rather than identity.
Bottom line: If you want to perform an identity comparison use the ReferenceEquals()
method. If you want to perform a value comparison, use Equals() but be aware that it
Page 23 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
will only work if the type has overridden the default implementation. Avoid operator
== with reference types (except perhaps strings), as it's simply too ambiguous.
If you define a user defined data type by using the struct keyword, Is it a a
value type or reference type?
Value Type
If you define a user defined data type by using the class keyword, Is it a a
value type or reference type?
Reference type
What is the base class from which all value types are derived?
[Link]
Page 24 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
It supports the principle of inheritance. Types can derive from other types,
called base types. The derived type inherits (with some restrictions) the
methods, properties, and other members of the base type. The base type can in
turn derive from some other type, in which case the derived type inherits the
members of both base types in its inheritance hierarchy. All types, including
built-in numeric types such as System.Int32 (C# keyword: int), derive ulti-
mately from a single base type, which is [Link] (C# keyword: ob-
ject). This unified type hierarchy is called the Common Type System (CTS).
For more information about inheritance in C#, see Inheritance (C# Pro-
gramming Guide).
Each type in the CTS is defined as either a value type or a reference type.
This includes all custom types in the .NET Framework class library and also your
own user-defined types. Types that you define by using the struct keyword are
value types; all the built-in numeric types are structs. Types that you define by
using the class keyword are reference types. Reference types and value types
have different compile-time rules, and different run-time behavior.
The following illustration shows the relationship between value types and reference
types in the CTS.
Page 25 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
What are the differences between value types and reference types?
1. Value types are stored on the stack where as reference types are stored on the
managed heap.
2. Value type variables directly contain their values where as reference variables holds
only a reference to the location of the object that is created on the managed heap.
3. There is no heap allocation or garbage collection overhead for value-type variables.
As reference types are stored on the managed heap, they have the over head of object
allocation and garbage collection.
4. Value types cannot inherit from another class or struct. Value types can only inherit
from interfaces. Reference types can inherit from another class or interface.
Explicit conversions: Explicit conversions require a cast operator. The source and
destination variables are compatible, but there is a risk of data loss because the type
of the destination variable is a smaller size than (or is a base class of) the source
variable.
Page 26 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
What type of data type conversion happens when the compiler encounters
the following code?
ChildClass CC = new ChildClass();
ParentClass PC = new ParentClass();
Implicit Conversion. For reference types, an implicit conversion always exists from a
class to any one of its direct or indirect base classes or interfaces. No special syntax is
necessary because a derived class always contains all the members of a base class.
No, the above code will not compile. Double is a larger data type than integer. An
implicit conversion is not done automatically bcos there is a data loss. Hence we have
to use explicit conversion as shown below.
double d = 9999.11;
int i = (int)d; //Cast double to int.
If you want to convert a base type to a derived type, what type of conversion
do you use?
Explicit conversion as shown below.
//Create a new derived type.
Car C1 = new Car();
// Implicit conversion to base type is safe.
Vehicle V = C1;
// Explicit conversion is required to cast back to derived type. The code below will
compile but throw an exception at run time if the right-side object is not a Car object.
Car C2 = (Car) V;
What operators can be used to cast from one reference type to another
without the risk of throwing an exception?
The is and as operators can be used to cast from one reference type to another without
the risk of throwing an exception.
Page 27 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
*******************************************************************
Designing Types
Type and member basics
Constants and Fields
Methods: Constructors, Operators
Assume that a class, Class1, has both instance and static constructors. Given
the code below, how many times will the static and instance constructors
fire?
Class1 c1 = new Class1();
Class1 c2 = new Class1();
Class1 c3 = new Class1();
Page 28 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
By definition, a static constructor is fired only once when the class is loaded. An
instance constructor on the other hand is fired each time the class is instantiated. So,
in the code given above, the static constructor will fire once and the instance
constructor will fire three times.
Static classes can be used when there is no data or behavior in the class that depends on object identity. i.e.
use a static class to contain methods that are not associated with a particular object. For example, it is a
common requirement to create a set of methods that do not act on instance data and are not associated to a
specific object in your code. You could use a static class to hold those methods.
Is it that creating a static class is same as creating a class that contains only static members and
a private constructor?
Yes. A private constructor prevents the class from being instantiated.
You have one base class virtual function how will you call the function from
derived class?
class a
{
public virtual int m()
{
return 1;
}
}
class b:a
{
Page 29 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
How make sure C# classes will interoperate with other .NET languages?
Ensure that the C# application code conforms to the Common Language Specification
(CLS). To help achieve compliance, add the [assembly:CLSCompliant(true)] global
attribute to all C# source files. This attribute will cause the C# compiler to throw an
error if a non-CLS-compliant feature is used.
Can derived classes have greater accessibility than their base types?
No, Derived classes cannot have greater accessibility than their base types. For
example the following code is illegal.
using System;
internal class InternalBaseClass
{
public void Print()
{
[Link]("I am a Base Class Method");
}
}
public class PublicDerivedClass : InternalBaseClass
{
Page 30 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
When you compile the above code an error will be generated stating "Inconsistent
accessibility: base class InternalBaseClass is less accessible than class
PublicDerivedClass".To make this simple, you cannot have a public class B that derives
from an internal class A. If this were allowed, it would have the effect of making A
public, because all protected or internal members of A are accessible from the derived
class.
No, a compile time error will be generated stating "Namespace elements cannot be
explicitly declared as private, protected, or protected internal"
Can the accessibility of a type member be greater than the accessibility of its
containing type?
No, the accessibility of a type member can never be greater than the accessibility of its
containing type. For example, a public method declared in an internal class has only
internal accessibility.
What is the default access modifier for a class, struct and an interface
declared directly with a namespace?
internal
No, you cannot specify access modifer for an interface member. Interface members are
always public.
Page 31 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Constants
What are constants?
Constants in C# are immutable values which are known at compile time and do not
change for the life of the program. Constants are declared using the const keyword.
Constants must be initialized as they are declared. You cannot assign a value to a
constant after it is declared. An example is shown below.
using System;
class Circle
{
public const double PI = 3.14;
public Circle()
{
//Error : You can only assign a value to a constant field at the time of declaration
//PI = 3.15;
}
}
class MainClass
Page 32 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
{
public static void Main()
{
[Link]([Link]);
}
}
Can you change the value of a constant filed after its declaration?
No, you cannot change the value of a constant filed after its declaration. In the
example below, the constant field PI is always 3.14, and it cannot be changed even by
the class itself. In fact, when the compiler encounters a constant identifier in C#
source code (for example, PI), it substitutes the literal value directly into the
intermediate language (IL) code that it produces. Because there is no variable address
associated with a constant at run time, const fields cannot be passed by reference.
using System;
class Circle
{
public const double PI = 3.14;
}
using System;
class Circle
{
public const double PI = 3.14;
}
class MainClass
{
public static void Main()
{
[Link]([Link]);
Circle C = new Circle();
// Error : PI cannot be accessed using an instance
// [Link]([Link]);
}
}
Page 33 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
using System;
public class MainClass
{
public static void Main()
{
int Number = 10;
[Link]([Link]());
}
}
In the above example [Link]() method will correctly give the string
representation of int 10, when you call the ToString() method.
If you have a Customer class as shown in the below example and when you call the
ToString() method the output does not make any sense. Hence you have to override
the ToString() method, that is inherited from the [Link] class.
using System;
public class Customer
{
public string FirstName;
public string LastName;
}
public class MainClass
{
public static void Main()
{
Customer C = new Customer();
[Link] = "David";
[Link] = "Boon";
[Link]([Link]());
}
}
The code sample below shows how to override the ToString() method in a class, that
would give the output you want.
using System;
public class Customer
{
public string FirstName;
public string LastName;
Page 34 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
{
public static void Main()
{
Customer C = new Customer();
[Link] = "David";
[Link] = "Boon";
[Link]([Link]());
}
}
Conclusion: If you have a class or a struct, make sure you override the inherited
ToString() method.
Fields
What are the 2 broad classifications of fields in C#?
1. Instance fields
2. Static fields
using System;
class Area
{
public static double PI = 3.14;
}
class MainClass
Page 35 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
{
public static void Main()
{
[Link]([Link]);
}
}
using System;
class Area
{
public readonly double PI = 3.14;
}
class MainClass
{
public static void Main()
{
Area a = new Area();
[Link]([Link]);
}
}
using System;
class Area
{
public readonly double PI = 3.14;
}
class MainClass
{
public static void Main()
{
Area a = new Area();
[Link] = 3.15;
[Link]([Link]);
}
}
No, PI is readonly. You can only read the value of PI in the Main() method. You cannot
assign any value to PI.
Page 36 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
class MainClass
{
public static void Main()
{
[Link]([Link]);
}
}
You cannot assign a value to the constant PI field.
The difference is that static read-only can be modified by the containing class, but
const can never be modified and must be initialized to a compile time constant. To
expand on the static read-only case a bit, the containing class can only modify it:
Page 37 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Why can’t you specify the accessibility modifier for methods inside the
interface?
They all must be public, and are therefore public by default.
How to inherit the class, but not the method inside it in C#? What is a sealed
method in C#? Can a method in C# be sealed? How to create a sealed
method?
If a method is not to be inherited, but the class is, then the method is sealed. It be-
comes a sealed method of a class. It is important to note here that in C#, a method
may not be implicitly declared as sealed. This means that a method cannot be sealed
directly. A method in C# can be sealed only when the method is an overriden method.
Once the overriden method is declared as sealed, it will not be further overriding of this
method. See code sample below, where an overriden method is sealed.
using System;
using [Link];
using [Link];
using [Link];
namespace sealed_method
{
class Program
{
public class BaseClass
{
public virtual void Display()
{
[Link]("Virtual method");
}
}
Page 38 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
// {
// [Link]("Here we try again to override dis-
play method which is not possible and will give error");
// }
//}
Page 39 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
What’s the implicit name of the parameter that gets passed into the set
method/property of a class?
Value. The data type of the value parameter is defined by whatever data type the
property is declared as.
class PassingValByVal
{
static void SquareIt(int x)
// The parameter x is passed by value.
// Changes to x will not affect the original value of x.
{
x *= x;
[Link]("The value inside the method: {0}",
x); //25
}
static void Main()
{
int n = 5;
[Link]("The value before calling the method:
{0}", n); //5
Page 40 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
A variable of a reference type does not contain its data directly; it contains a reference to its data. When you
pass a reference-type parameter by value, it is possible to change the data pointed to by the reference, such
as the value of a class member. However, you cannot change the value of the reference itself; that is, you
cannot use the same reference to allocate memory for a new class and have it persist outside the block.
Example: Passing Reference Types by Value
class PassingRefByVal
{
static void Change(int[] pArray)
{
pArray[0] = 888; // This change affects the original element.
pArray = new int[5] {-3, -1, -2, -3, -4}; // This change is lo-
cal.
[Link]("Inside the method, the first element
is: {0}", pArray[0]); //-3
}
Change(arr);
[Link]("Inside Main, after calling the method,
the first element is: {0}", arr [0]); //888
}
}
class PassingValByRef
{
static void SquareIt(ref int x)
// The parameter x is passed by reference.
// Changes to x will affect the original value of x.
{
x *= x;
[Link]("The value inside the method: {0}",
x); //5
}
static void Main()
{
int n = 5;
[Link]("The value before calling the method:
{0}", n); //5
Page 41 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
If you pass a reference type parameter using the ref or out keyword, you can change the value of the
reference itself; that is, you can use the same reference to allocate memory for a new class and have it
persist outside the block.
Example: Passing Reference Types by Reference
class PassingRefByRef
{
static void Change(ref int[] pArray)
{
// Both of the following changes will affect the original vari-
ables:
pArray[0] = 888;
pArray = new int[5] {-3, -1, -2, -3, -4};
[Link]("Inside the method, the first element
is: {0}", pArray[0]); //-3
}
Change(ref arr);
[Link]("Inside Main, after calling the method,
the first element is: {0}", arr[0]); //-3
}
}
2) Properties allow you to perform special processing when a value is set (or gotten).
You can't do this with fields because there is no "hook" to put code in. For example,
here is some C# code that will make sure a field is never null. You can't do this with
fields.
Page 42 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
3) Similar #3 above, properties give you a place to hook in events. I could easily add a
method to invoke a FirstNameChanged event in the above setter. You can't do this with
fields. This is probably the most important difference between using fields and
properties.
The definition of the Main method starts with its access modifier i.e. public, hence any
object can call this method. Its followed by the keyword static, this keyword makes
turns the method into a class level member. Hence you do not have to first create an
object of the class to call the Main method. I understand things might seem a bit
cloudy now, but they will get clarified as we move on.
Then there is the return type, after every method finishes execution it returns the
control back to the caller. When a method returns, it has to have a return value. In this
case since this method is going to return no value the void keyword is used to denote
that the method returns no value. Finally, there is the method name, Main with a set of
empty parentheses. Like the classes, methods too use scope operators i.e. { } to
define the scope of the method. All the code of the method has to be packaged within
the scope operators for the method.
There is a special significance attached with the method Main in C#. When you click on
an application to run it, the runtime should know from where (which class, which
method) it should start executing the code. In C#, like many other programming
languages there is the Main method which the runtime uses by default to start running
the application. Hence the Main method is also known as the entry point of the
application.
Note: C / C++ / Java programmers its called the Main method with a capital M, unlike
other languages.
Note: Unlike C++ Main method is not a global function, it has to be defined as a class
member.
In Java, the Main method cannot have any other access modifier than 'public'.
How is it that in C# you can have a private access modifier to the Main
method? Can anybody throw any light, comparing JVM with CLR?
If you refer to Main method as the entry point of the application, then you have a
similar situation in C# than in Java, in c# the entry point MUST be declared as static
void Main() , if that is not present the compiler will give you an error.
Now there is nothing that prohibits you to name a method Main () on any class, only
that it will no be the entry point of the application.
Page 43 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
But it’s not true that "in c# the entry point MUST be declared as static void Main (), if
that is not present the compiler will give you an error." Infact it works even if you
declare the entry point as "private static void Main ()”, the compiler gives no error,
neither the CLR throws any run-time error!!! Isn’t this strange??!! That’s precisely the
point of confusion. You may try this out.
Public, private, protected and others are access attributes that are enforced primarily
by the compiler (at runtime only when dynamic invocation is involved). Beyond that,
the runtime is free to accept or ignore the access specifiers - and in the case of Main, it
kindly ignores them.
Matters such as these (and this is but one example of many others) are
implementation specific details for the runtime, not for a particular language.
Can you modify the access modifiers while overriding a method in a class?
No. An override declaration cannot change the accessibility of the virtual method.
Both the override method and the virtual method must have the same access level
modifier.
An override method provides a new implementation of a member inherited from a
base class. The method overridden by an override declaration is known as the
overridden base method. The overridden base method must have the same signature
as the override method. You cannot override a non-virtual or static method. The
overridden base method must be virtual, abstract, or override.
Can you declare an override method to be static if the original method is not
static?
No. The signature of the virtual method must remain the same. (Note: Only the
Page 44 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
What is Private Constructor? What is its use? Can you create instance of a
class which has Private Constructor?
When a class declares only private instance constructors, it is not possible for classes
outside the program to derive from the class or to directly create instances of it.
(Except Nested classes)
Make a constructor private if:
- You want it to be available only to the class itself. For example, you might have a
special constructor used only in the implementation of your class' Clone method.
- You do not want instances of your component to be created. For example, you may
have a class containing nothing but Shared utility functions, and no instance data.
Creating instances of the class would waste memory.
Can abstract classes have constructors? If the answer is yes, when do they
get called?
Yes, we can have constructor in abstract class. But we can not make instance of the
abstract class. Instead, we can make a reference to that abstract class and when we
make a new object of the class which extends the abstract class, the constructor of
abstract class get called.
Page 45 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
[Link]();
}
Output
...in abstract class' constructor
...in ShowAbstract
...in Show
using System;
class Test
{
Test()
{
throw new Exception();
}
~Test()
{
[Link]("Finalized");
}
Page 46 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
[Link]();
}
}
What is the order in which the destructors and the constructors are called in C++ and C#?
Use the examples of some Base classes and Derived Classes.
The order is:
Base constructor
Derived constructor
Derived destructor
Base destructor
Page 47 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
}
What are the differences between C# finalizers and Java destructors?
C# features hybrid destructors which use a C++ style, destructor syntax yet share
most of their semantics with Java finalizers.
The following C# and Java examples are equivalent:
using System;
Page 48 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
{
~CSharpClass()
{
}
}
public class JavaClass
{
public void finalize()
{
}
}
Although C# destructors automatically call the base class destructor after execution,
this does not happen in the Java finalizer system.
class B : A
{
B() : base (10) // call base constructor A(10)
{}
Page 49 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
{}
Properties
What are Properties in C#? Explain with an example.
Properties in C# are class members that provide a flexible mechanism to read, write,
or compute the values of private fields. Properties can be used as if they are public
data members, but they are actually special methods called accessors. This enables
data to be accessed easily and still helps promote the safety and flexibility of methods.
In the example below _firstName and _lastName are private string variables which are
accessible only inside the Customer class. _firstName and _lastName are exposed
using FirstName and LastName public properties respectively. The get property
accessor is used to return the property value, and a set accessor is used to assign a
new value. These accessors can have different access levels. The value keyword is
used to define the value being assigned by the set accessor. The FullName property
computes the full name of the customer. Full Name property is readonly, because it
has only the get accessor. Properties that do not implement a set accessor are read
only.
The code block for the get accessor is executed when the property is read and the
code block for the set accessor is executed when the property is assigned a new value.
Page 50 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
using System;
class Customer
{
// Private fileds not accessible outside the class.
private string _firstName = [Link];
private string _lastName = [Link];
private string _coutry = [Link];
}
class MainClass
{
public static void Main()
{
Customer CustomerObject = new Customer();
Page 51 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
using System;
class Circle
{
private static double _pi = 3.14;
public static double PI
{
get
{
return _pi;
}
}
}
class MainClass
{
public static void Main()
{
[Link]([Link]);
}
}
Page 52 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
{
get
{
// Get codes goes here
}
set
{
// Set codes goes here
}
}
Where the modifier can be private, public, protected or internal. The return type can be
any valid C# types. The 'this' is a special keyword in C# to indicate the object of the
current class. The formal-argument-list specifies the parameters of the indexer.
using System;
class Customer
{
private string _firstName = [Link];
private string _lastName = [Link];
Page 53 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
get
{
return _lastName + ", " + _firstName;
}
}
}
class BankCustomer : Customer
{
// Overiding the FullName virtual property derived from customer class
public override string FullName
{
get
{
return "Mr. " + FirstName + " " + LastName;
}
}
}
class MainClass
{
public static void Main()
{
BankCustomer BankCustomerObject = new BankCustomer();
[Link] = "David";
[Link] = "Boon";
[Link]("Customer Full Name is : " + [Link]);
}
}
using System;
abstract class Customer
{
private string _firstName = [Link];
private string _lastName = [Link];
Page 54 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
{
return _lastName;
}
set
{
_lastName = value;
}
}
// FullName is abstract
public abstract string FullName
{
get;
}
}
class BankCustomer : Customer
{
// Overiding the FullName abstract property derived from customer class
public override string FullName
{
get
{
return "Mr. " + FirstName + " " + LastName;
}
}
}
class MainClass
{
public static void Main()
{
BankCustomer BankCustomerObject = new BankCustomer();
[Link] = "David";
[Link] = "Boon";
[Link]("Customer Full Name is : " + [Link]);
}
}
Page 55 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Essential Types
Array
Strings
Delegates
Interface
Generics
Collections
Attributes
Reflection
Array
What is an array?
An array is a data structure that contains several variables of the same type.
How do you initialize a two-dimensional array that you don’t know the dimen-
sions of?
int [, ] myArray; //declaration or int [][] myArray;
myArray= new int [5, 8]; //actual initialization
Page 56 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
myTable[0][2] = 11;
Limitation of Arrays
The size of an array is always fixed and must be defined at the time of instantiation of
an array.
Secondly, an array can only contain objects of the same data type, which we need to
define at the time of its instantiation.
How can you sort the elements of the array in descending order?
Using [Link]() and [Link]() [Link][] arr = new int[3];
arr[0] = 4;
arr[1] = 1;
arr[2] = 5;
[Link](arr);
[Link](arr);
What is cloning?
Cloning is the ability to make an exact copy (a clone) of an instance of a type. Cloning
may take one of two forms: a shallow copy or a deep copy.
Page 57 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
this DataTable, just for making minor changes to the schema or adding a new row etc,
it would be more wise just to clone an existing object and work on that, rather than
recreating a new DataTable, which can require more time and resources.
Cloning is also widely applicable to Arrays and Collections, where you need a copy of
existing elements many a time.
Page 58 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
.NET defines an interface called IClonable which has to be implemented by classes that
need functionality beyond the scope of shallow cloning (for deep cloning). We need to
provide a suitable implementation in the Clone method of the interface to do the same.
There are various ways to implement deep cloning. One method is to serialize the
object into a memory stream and deserialize it back into a new object. We would need
to use a Binary formatter or SOAP formatter which do a deep serialization. The
problem with this approach is that the class and its members (the entire object graph)
have to be marked as serializable, else the formatter would through an exception.
Reflection may be another method to achieve the same. One good article written by
Amir Harel caught my eye. He provides a good clone implementation using this
method. The discussion on the article is good too! Here's the link
[Link]
Understand that, for either of the methods discussed above, the member types must
support cloning themselves for deep cloning to be successful. That is, the object graph
must be serializable or the individual member must provide an implementation of
IClonable. If this is not the case, then we would not be able to deep clone the object at
all!
Page 59 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
There is no need to deal with static fields when performing a cloning operation. There
is only one memory location reserved for each static field per class, per application
domain. Besides, the cloned object will have access to the same static fields as the
original.
How to make a deep copy of an object (cloning for a user defined class)?
Making a deep copy is the second way of cloning an object. A deep copy will make a
copy of the original object just as the shallow copy does. However, a deep copy will
also make separate copies of each reference type field in the original object. Therefore,
if the original object contains a StreamWriter type field, the cloned object will also
contain a StreamWriter type field, but the cloned object's StreamWriter field will point
to a new StreamWriter object, not the original object's StreamWriter object. Support for
deep copying is not automatically provided by the Clone
method or the .NET Framework. Instead, the following code illustrates an easy way of
implementing a deep copy:
For deep copy of a user defined class, a class should implement IClonable interface.
Have you ever used the Clone() method of DataSet? This method creates an empty
class with same structure as original DataSet.
You can write your own clonable classes. To do so, you must implement IClonable. The
following code shows a clonable Test class.
using [Link];
using [Link];
Page 60 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Basically, the original object is serialized out to a memory stream using binary
serialization, then it is deserialized into a new object, which is returned to the caller.
Note that it is important to
reposition the memory stream pointer back to the start of the stream before calling the
Deserialize method; otherwise, an exception indicating that the serialized object
contains no data will be thrown.
Performing a deep copy using object serialization allows the underlying object to be
changed without having to modify the code that performs the deep copy. If you
performed the deep copy by hand, you'd have to make a new instance of all the
instance fields of the original object and copy them over to the cloned object. This is a
tedious chore in and of itself. If a change is made to the fields of the object being
cloned, the deep copy must also change to reflect this
modification. Using serialization, you rely on the serializer to dynamically find and
serialize all fields contained in the object. If the object is modified, the serializer will still
make a deep copy
without any code modifications.
The Clone() method returns a new array (a shallow copy) object containing all the
elements in the original array. The CopyTo() method copies the elements into another
existing array. Both perform a shallow copy. A shallow copy means the contents (each
array element) contains references to the same object as the elements in the original
array. A deep copy (which neither of these methods performs) would create a new
instance of each element's object, resulting in a different, yet identical object.
How can you sort the elements of the array in descending order?
By calling Sort() and then Reverse() methods.
*******************************************************************************
Strings
What is a string?
A string is basically a sequence of characters. Each character is a 16 bit Unicode
character in the range U+0000 to U+FFFF.
Page 61 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
processing tasks more time- or space-efficient at the cost of requiring more time when
the string is created or interned. The distinct values are stored in a string intern
pool.
String interning is supported by some modern object-oriented programming languages,
including Python, Ruby (with its symbols), Java and .NET languages.
The single copy of each string is called its 'intern'.
The string intern pool is a table that contains a single reference to each unique literal
string declared or created programmatically in your application. The Common
Language Runtime (CLR) uses the intern pool to minimize string storage requirements.
As a result, an instance of a literal string with a particular value only exists once in the
system. For example, if you assign the same literal string to several different variables,
at runtime, the CLR retrieves the unique reference to that literal string from the intern
pool and assigns it to each variable.
2) It happens automatically, when you load an assembly. All the string literals
in the assembly are intern’ed. This is expensive and – in retrospect – may have
been a mistake. In the future we might consider allowing individual assemblies
to opt-in or opt-out. Note that it is always a mistake to rely on some other
assembly to have implicitly intern’ed the strings it gives you. Through
versioning, that other assembly might start composing a string rather than
using a literal.
The following code example uses three strings that are equal in value to determine
whether a newly created string and an interned string are equal.
// Sample for [Link](String)
using System;
using [Link];
class Sample {
public static void Main() {
Page 62 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
String s1 = "MyTest";
String s2 = new StringBuilder().Append("My").Append("Test").ToString();
String s3 = [Link](s2);
[Link]("s1 == '{0}'", s1);
[Link]("s2 == '{0}'", s2);
[Link]("s3 == '{0}'", s3);
[Link]("Is s2 the same reference as s1?: {0}", (Object)s2==(Object)s1);
[Link]("Is s3 the same reference as s1?: {0}", (Object)s3==(Object)s1);
}
}
/*
This example produces the following results:
s1 == 'MyTest'
s2 == 'MyTest'
s3 == 'MyTest'
Is s2 the same reference as s1?: False
Is s3 the same reference as s1?: True
*/
In the past, you had to call .ToString() on the strings when using the == or !=
operators to compare the strings’ values. That will still work, but the C# compiler now
automatically compares the values instead of the references when the == or !=
operators are used on string types. If you actually do want to compare references, it
can be done as follows: if ((object) str1 == (object) str2) { … } Here’s an example
showing how string compares work:using System;
Page 63 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Of course, doing so comes at the cost of creating multiple string objects in memory when doing
some intensive string computation. In this case you need to use the [Link]
class that provides a safe way to work with mutable string.
Another cool thing about string immutability is that even though [Link] is a class, string ob-
jects get compared with equivalence, as a value type. This is possible because we can consider
that the identity of an immutable object is its state. For example:
Page 64 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Why .NET engineers decided that string should be immutable? Or Why String class is
immutable?
There are several reasons for designing string class as immutable. Below are reasons:
To achieve memory efficiency: CLR internally maintains the "String Pool". To achieve the
memory efficiency, CLR will refer the String object from pool. It will not create the new
String objects. So, whenever you create a new string literal, CLR will check in the pool
whether it already exists or not. If already present in the pool, just give the reference to the
same object or create the new object in the pool. There will be many references point to the
same String objects, if someone changes the value, it will affect all the references.
To avoid corrupted keys in collections: Because programmers will never get a race
conditions because of a corrupted string. Also because string are well adapted to be key in
hashtables (i.e [Link]<K,V>). Hashtables are almost a
magic way to enhance dramatically performance of your code. (I said magic because under
the hood hashtables rely on prime numbers properties and prime numbers are magic!). The
objects on which the hash values are computed must be immutable to make sure that the
hash values will be constant in time. Indeed, hash value is computed from the state of the
object (or eventually a sub-state of the object, then only this sub-state must be immutable).
To maintain security: Look at this example: We have a file open method with login check.
We pass a String to this method to process authentication which is necessary before the
call will be passed to OS. If String was mutable it was possible somehow to modify its
content after the authentication check before OS gets request from program then it is
possible to request any file. So, if you have a right to open text file in user directory but then
on the fly when somehow you manage to change the file name you can request to open
"passwd" file or any other. Then a file can be modified and it will be possible to login directly
to OS.
If strings are mutable then there would be no String pool implementation and the performance gains
of the String pool become lost.
Avoid an assignment to a variable from outside the class. To further restrict the
access we can use a private access modifier. Above do not provide any method
where we modify the instance variables.
Avoid sub classing. How if somebody creates a sub class from our up till now im-
mutable class? Yes, here lies the problem. The new subclass can contain methods,
which over ride our base class (immutable class) methods. Here he can change the
variable values. Hence make the methods in the class also sealed. Or a better ap-
proach. Make the immutable class itself sealed. Hence cannot make any sub classes,
so no question of over ridding.
Page 65 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Don't allow writeable fields or properties or have methods that change the state of
the type.
However, the questions started revolving around how [Link] have methods to
update the string but in reality it creates a new instance. All of this is really simple to
achieve.
Example:
Let’s think of an Employee immutable class, where the class has a Name and Salary prop-
erty and allows an increment to be made to the Salary. However, since Employee is im-
mutable the Increment results in a new instance of the class to be created with an incre-
mented Salary.
In the code above there is no field and the properties are get only. So there is no possibility
of making state changes with these. The Increment method creates a new instance of the
class with the increment without touching the class on which it is called. All of this makes
Employee an immutable type.
Note that with auto-implemented properties, both a get and set accessor are required. You
make the class immutable by declaring the set accessors as private. However, when you de-
clare a private set accessor, you cannot use an object initializer to initialize the property.
You must use a constructor or a factory method.
//Example 1:
Page 66 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
// Public constructor.
public Contact(string contactName, string contactAddress)
{
Name = contactName;
Address = contactAddress;
}
}
//Example 2:
// This class is immutable. After an object is created,
// it cannot be modified from outside the class. It uses a
// static method and private constructor to initialize its proper-
ties.
public class Contact2
{
// Read-only properties.
public string Name { get; private set; }
public string Address { get; private set; }
// Private constructor.
private Contact2(string contactName, string contactAddress)
{
Name = contactName;
Address = contactAddress;
}
Page 67 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Output:
Null Object is []
Real Object is [StringTest]
i is [10]
foo == bar ? False
bar == bar ? True
Page 68 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
keyword are the same, and you can use whichever naming convention you prefer. The
String class provides many methods for safely creating, manipulating, and comparing
strings.
[Link](s1);
// Output: First String Second String
The output of the above code is "Hello" and not "Hello C#". This is because, if you
create a reference to a string, and then "modify" the original string, the reference will
continue to point to the original object instead of the new object that was created when
the string was modified.
Page 69 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Text written to be in
three lines.
*/
Page 70 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
In other words delegates are function pointers that point to function of matching signa-
tures. Function pointers which are extensively used in c/c++ to points to a function holds
only the memory address of the function, it doesn’t carry further information about the
function parameters, return type etc. On the other hand .NET framework has introduced a
type-safe mechanism called delegates, with automatic verification of the signature by
the compiler.
So we can say that delegates are type-safe, object oriented, secure .NET objects which
can be used to invoke methods of matching signature.
While using delegates it is very much necessary to make sure that the functions which
the delegates points has the same number of argument type and same return type. For
example if we have a method that takes a single string as a parameter and another method
that takes two string parameters, then we need to have two separate delegate type for
each method.
A delegate is called single cast delegate if it invokes a single method. In other words we
can say that SingleCast Delegates refer to a single method with matching
signature. SingleCast Delegates derive from the [Link] class
The signature of a single cast delegate is shown below. The letters in italics can be replaced
with your own names and parameters.
When the compiler compiles the statement above, it internally generates a new class type.
This class is called DelegateName and derives from [Link]. Just to make sure
just check the ILDisassembler code to check that this is happening. As an example let us
Page 71 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
create a single cast delegate named MyDelegate which would point to a function MyFunc-
tion. The code appears as below,
public delegate Boolean MyDelegate(Object sendingobj, Int32 x);
}
}
MultiCast Delegates are nothing but a single delegate that can invoke multiple
methods of matching signature. MultiCast Delegate derives from [Link]-
castDelegate class which is a subclass of [Link].
In Multi-Casting basically we create a single delegate that in turn invokes multiple en-
capsulated methods. We can use MultiCast Delegates when multiple calls to differ-
ent methods are required. For example if we are required to call two methods on a single
button click event or mouse over event then using MultiCast Delegates we can eas-
ily call the methods.
What is less obvious about the one or two lines of code, is that a delegate type definition is
a shorthand syntax for defining a class.
Page 72 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Each level within the delegate hierarchy provides a different set of services.
[Link] is a container of the data for what method to call on a particular object.
With [Link] comes the additional capability of not only invoking a
method on a single object, but on a collections of objects. This enables multiple subscribers
to an event.
Why delegate types are derived from MulticastDelegate class why not it directly
derive from Delegate class?
[Link]
multicastdelegate-class-why-not-it-directly-d
I have a very basic question regarding delegate types. I compared the memebers of Delegate and
MulticastDelegate classes in object browser and I couldn't find any new additional member present
in MulticastDelegate. I also noticed that the Delegate class has GetInvocationList virtual method.
So I assume that the Delegate class should have the capability to hold references to multiple
methods. If my assumption is correct I wonder why not custom delegate types directly derive from
the Delegate class instead of MulticastDelegate class.
Basically the split of Delegate and MulticastDelegate is for historical reasons. Originally
there were going to be delegates which couldn't be combined and ones which could... but that
turned out not to be a useful distinction. Apparently that was only discovered when it was a bit too
late to rip MulticastDelegate out of the framework/CLR.
The [Link] class is derived from [Link], which is itself derived from
[Link]. The reason why there are two delegate classes is historical and unfortunate; there
should be just one delegate class in the FCL. Sadly, you need to be aware of both of these classes
because even though all delegate types you create have MulticastDelegate as a base class, you'll
occasionally manipulate your delegate types by using methods defined by the Delegate class
instead of the MulticastDelegate class. [...]
Page 73 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
[Link]
On its own, [Link] only identifies one subscriber to an event. This would work for
a method pointer, for example a predicate used in a sort routine, but it would rarely be
sufficient in a publish-subscribe/observer pattern. (In fact, in early betas of C# 1.0,
Microsoft realized that using a single delegate was rare enough to avoid the need of even
providing a means of defining a “single-cast” delegate.)
[Link] therefore, adds to delegates the support for notifying multiple
subscribers. This is enabled through [Link]’s containment of another
[Link] instance. When we add a subscriber to a multicast delegate, the
MulticastDelegate class creates a new instance of the delegate type, stores the object
reference and the method pointer for the added method into the new instance, and adds
the new delegate instance as the next item in a list of delegate instances. In effect, the
MulticastDelegate class maintains a linked list of delegate objects.
The - operator can be used to remove a component delegate from a multicast delegate.
using System;
// Define a custom delegate that has a string parameter and returns void.
delegate void CustomDel(string s);
class TestClass
{
// Define two methods that have the same signature as CustomDel.
static void Hello(string s)
{
[Link](" Hello, {0}!", s);
}
Page 74 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
What is the problem of invoking each delegate instance inside multicast delegate
in a sequential manner?
When invoking the multicast delegate, each delegate instance in the linked list is called
sequentially. (Generally, delegates are called in the order they were added but this
behavior is not specified within the CLI specification and furthermore, it can be overridden.
Therefore, programmers should not depend on an invocation order.) This sequential
Page 75 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
invocation, however, leads to problems if the invoked method throws an exception or if the
delegate itself returns data.
Error handling makes awareness of the sequential notification critical. If one subscriber
throws an exception then later subscribers in the chain do not receive the notification.
Consider, for example, a heater class with an OnTemperatureChanged() method that threw
an exception as shown in Listing 3.
class Heater
{
...
public voidOnTemperatureChanged( floatnewTemperature)
{
throw new NotImplementedException();
}
...
}
Figure 1 shows the effect in a sequence diagram where cooler is an additional subscriber
that also has a method matching the TemperatureChangeHandler() signature.
Even though cooler subscribed to receive messages, heater exception terminates the chain
and prevents the cooler object from receiving notification.
To avoid this problem, so that all subscribers receive notification regardless of the behavior
of earlier subscribers, you must manually enumerate through the list of subscribers and call
them individually. Listing 4shows an implementation for a CurrentTemperature property
that fires change notifications:
Page 76 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Enter temperature: 45
Cooler: Off
This listing demonstrates that we can retrieve a list of subscribers from a delegates
GetInvocationList() method. Enumerating over each item in this list returns the individual
subscribers. If we then place each invocation of a subscriber within a try catch block we can
Page 77 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
handle any error conditions before continuing on with the enumeration loop. In our sample,
even though [Link]() throws an exception, cooler still receives the
notification of the temperature change.
Delegate object is pointing to 5 methods? How the methods would get called? If there
is an exception thrown by 2nd method, what is going to happen? How do you ensure
that delegate continues to execute remaining methods?
Or, how to handle exception in multicast delegate in C#?
[Link]
delegate-in-c
You can loop through all the delegates’ registered in the multicast list and call each of them in turn
while wrapping each call in a try - catch block.
Otherwise the invocations of the subsequent delegates in the multicast after the delegate with the
exception will be aborted. Consider the code using GetInvocationList
foreach (var singleDelegate in [Link]()) {
try {
[Link](new object[] { sender, eventArg });
} catch (Exception ex) {
// uck
}
}
which individually calls each delegate that would have been invoked with
[Link](sender, eventArg)
This is how to declare a delegate with the signature you describe. All delegates are potentially
multicast, they simply require initialization. Such as:
Page 78 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Foo f1 = IsGreaterThanNow;
Foo f2 = IsLessThanNow;
Foo fAll = f1 + f2;
Calling fAll, in this case would call both IsGreaterThanNow() and IsLessThanNow().
What this doesn't do is give you access to each return value. All you get is the last value returned. If
you want to retrieve each and every value, you'll have to handle the multicasting manually like so:
foreach(Foo f in [Link]())
{
List<bool> returnValues = new List<bool>();
[Link](f(timestamp));
}
Here is my scenario. I have class with 10 methods, those methods are atomic, and are only
10 lines of code max. So I was thinking, instead of handling the exceptions in each function,
would it be possible, to create a delegate (? not sure its the right word here)
That so called wrapped function would execute those atomic functions and handle their
exceptions, thus allowing me to centralize exception handling.
Is this possible in C# using delegate or Func, or maybe there is another way to centralize
error handling that I might have missed?
using System;
namespace ConsoleApp
{
class Example {
public void Run() {
catchy(crashA); // Calling defined functions
catchy(crashB);
catchy(()=> {
throw new ArgumentException("Anonymous function...");
});
}
void crashA() {
//...
throw new ArgumentException("another error");
}
void crashB() {
//...
throw new ArgumentException("another error");
}
void catchy(Action action) {
try {
Page 79 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
action();
} catch (Exception ex) {
[Link](ex);
// do something
}
}
}
class MainClass
{
public static void Main (string[] args)
{
new Example().Run();
[Link]();
[Link] ("Hello World!");
}
}
}
[Link]/BeginInvoke executes on the thread that owns the Control's handle (most of time it
is the UI thread).
For Windows Forms apps, I would suggest that you should usually use BeginInvoke. That way you
don't need to worry about deadlock, for example - but you need to understand that the UI may not
have been updated by the time you next look at it! In particular, you shouldn't modify data which the
UI thread might be about to use for display purposes. For example, if you have a Person with
FirstName and LastName properties, and you did:
then the UI may well end up displaying "Keyser Spacey". (There's an outside chance it could
display "Kevin Soze" but only through the weirdness of the memory model.)
Unless you have this sort of issue, however, [Link] is easier to get right, and will
avoid your background thread from having to wait for no good reason. Note that the Windows
Page 80 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Forms team has guaranteed that you can use [Link] in a "fire and forget" manner -
i.e. without ever calling EndInvoke. This is not true of async calls in general: normally every
BeginXXX should have a corresponding EndXXX call, usually in the callback.
To reference that delegate outside of MyClass you would write the following:
[Link] myDel;
Page 81 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Since a delegate is a type that inherits from delegate you cannot declare a
delegate within an interface, because you cannot declare nested types in an
interface. That being said it is recommended to declare delegate type outside of a class
and inside a namespace, because delegates really are just classes.
What is an event?
An event in C# is a way for a class to provide notifications to clients of that class when
some interesting thing happens to an object. The most familiar use for events is in
graphical user interfaces; typically, the classes that represent controls in the interface
have events that are notified when the user does something to the control (for exam-
ple, click a button).
Events, however, need not be used only for graphical interfaces. Events provide a gen-
erally useful way for objects to signal state changes that may be useful to clients of
that object. Events are an important building block for creating classes that can be
reused in a large number of different programs.
Events are declared using delegates. An event is a way for a class to allow clients to
give it delegates to methods that should be called when the event occurs. When the
event occurs, the delegate(s) given to it by its clients are invoked.
This example shows that it is possible to declare an event in an interface and imple-
ment it in a class:
// event_keyword.cs
using System;
public delegate void MyDelegate(); // delegate declaration
public interface I
{
event MyDelegate MyEvent;
void FireAway();
}
Page 82 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
*******************************************************************************
Generics
What is a generic type?
A generic type is a type that uses generic type parameters. For example, the type LinkedList<K,T>, defined
as:
public class LinkedList<K,T>
{...}
is a generic type, because it uses the generic type parameters K and T, where K is the list's key and T is the
type of the data item stored in the list. What is special about generic types is that you code them once, yet
you can use them with different parameters. Doing so has significant benefits—you reuse your development
and testing efforts, without compromising type safety and performance, and without bloating your code.
Page 83 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
• Type Safety When a generic algorithm is used with a specific type, the
compiler and
the CLR understand this and ensure that only objects compatible with the
specified
data type are used with the algorithm. Attempting to use an object of an
incompatible
type will result in either a compiler error or a run-time exception being thrown.
In the
example, attempting to pass a String object to the Add method results in the
compiler
issuing an error.
• Cleaner Code Since the compiler enforces type safety, fewer casts are
required in your
source code, meaning that your code is easier to write and maintain. In the last
line of
SomeMethod, a developer doesn't need to use a (DateTime) cast to put the
result of the
indexer (querying element at index 0) into the dt variable.
• Better Performance Before generics, the way to define a generalized
algorithm was to
define all of its members to work with the Object data type. If you wanted to use
the
algorithm with value type instances, the CLR had to box the value type instance
prior to
calling the members of the algorithm. As discussed in Chapter 5, "Primitive,
Reference,
and Value Types," boxing causes memory allocations on the managed heap,
which
causes more frequent garbage collections, which, in turn, hurt an application's
performance.
Since a generic algorithm can now be created to work with a specific value
type, the instances of the value type can be passed by value, and the CLR no
longer
has to do any boxing. In addition, since casts are not necessary (see the
previous
bullet), the CLR doesn't have to check the type safety of the attempted cast,
and this
results in faster code too.
•Reuse development and testing efforts You code them once, yet you can
use them with different parameters.
uses two type parameters - K and T, where K is the list's key and T is the type of the data item stored
in the list. Using generic type parameters allows the linked list to defer the decision on the actual
types to use. In fact, it is up to the client of the generic linked list to specify the generic type
parameters to use.
Page 84 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
A generic type argument is the type the client specifies to use instead of the type parameter. For
example, given this generic type definition and declaration:
LinkedList<string>
To qualify as a constructed type you can also specify type parameters to the generic type:
Then the following declarations of LinkedList<K,T> member variables are all open constructed types:
Page 85 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
{...}
Then the following declarations of LinkedList<K,T> member variables are all closed constructed types:
You need to specify which types to use for K, the list's key, and T, the data items stored in the list. You
specify the types in two places: when declaring the list's variable and when instantiating it:
Once you specify the types to use, you can simply call methods on the generic type, providing
appropriate values of the previously specified types.
A generic type that has type arguments already, such as LinkedList<int,string> is called a constructed
type.
When specifying type arguments for generic types, you can actually provide type parameters. For
example, consider this definition of the Node<K,T> class, which is used as a node in a linked list:
class Node<K,T>
{
public K Key;
public T Item;
public Node<K,T> NextNode;
Page 86 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
}
}
The Node<K,T> class contains as a member variable a reference to the next node. That member must
be provided with the type to use instead of its generic type parameters. The node specifies its own
type parameters in this case.
Another example of specifying generic type parameters to a generic type is how the linked list itself
may declare and use the node:
Note that the use of K and T in the linked list as the names of the type arguments is purely for
readability purposes, to make the use of the node more consistent. You could have defined the linked
list with any other generic type parameter names, in which case, you need to pass them along to the
node as well:
Page 87 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
//Additional members
}
The problem with that approach is that you will need a type-specific interface and implementation per
data type you need to interact with, such as a string or a Customer. If you have a defect in your
handling of the data items, you will need to fix it in as many places as types, and that is simply error-
prone and impractical. With generics, you get to define and implement your logic once, yet use it with
any type you want.
Generic types are not covariant. Meaning, you cannot substitute a generic type with a specific type
argument, with another generic type that uses a type argument that is the base type for the first type
argument. For example, the following statement does not compile:
class MyBaseClass
{}
class MySubClass : MyBaseClass
{}
class MyClass<T>
{}
//Will not compile
MyClass<MyBaseClass> obj = new MyClass<MySubClass>();
Using the same definition as in the example above, it is also true that MyClass<MyBaseClass> is not
the base type of MyClass<MySubClass>:
[Link](typeof(MyClass<MyBaseClass>) !=
typeof(MyClass<MySubClass>).BaseType);
This would not be the case if the generic types were contra-variant.
Because generics are not covariant, when overriding a virtual method that returns a generic type
parameter, you cannot provide a subtype of that type parameter as the definition of the overriding
method:
class MyBaseClass<T>
{
Page 88 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
That said, constraints are covariant. For example, you can satisfy a constraint using a sub type of the
constraint's type:
class MyBaseClass
{}
class MySubClass : MyBaseClass
{}
class MyClass<T> where T : MyBaseClass
{}
Finally, generics are invariant, because there is no relationship between two generic types with
different type arguments, even if those type arguments do have an is-as relationship, for example,
List<int> has nothing to do with List<object>, even though an int is an object.
What Can Define Generic Type Parameters? What Types Can Be Generic?
Classes, interfaces, structures and delegates, can all be generic types. Here are a few examples from
the .NET Framework:
Page 89 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
In addition, both static and instance methods can rely on generic type parameters, independent of the
types that contain them:
Enumerations on the other hand cannot define type parameters, and the same goes for attributes.
Can Methods Define Generic Type Parameters? How Do I Call Such Methods?
Yes. Both instance and static methods can define generic type parameters, and do so independently of
their containing class. For example:
Page 90 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
The benefit of a method that defines generic type parameters is that you can call the method passing
each time different parameter types, without ever overloading the method. When you call a method
that defines generic type parameters, you need to provide the type arguments at the call site:
[Link]<int>(3);
[Link]<string>("Hello");
If type-inference is available, you can omit specifying the type arguments at the call site:
[Link](3);
[Link]("Hello");
Can I Derive From a Generic Type Parameter?
You cannot define a class that derives from its own generic type parameter:
Page 91 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
When invoking these methods, you can omit specifying the type arguments for both the instance and
the static methods:
Note that type inferring is possible only when the method takes an argument of the inferred type
arguments. For example, in the CreateInstance<T>() method of the Activator class, defined as:
type inference is not possible, and you need to specify the type arguments at the call site:
class MyClass
{...}
MyClass obj = [Link]<MyClass>();
Note also that you cannot rely on type inference at the type level, only at the method level. In the
following example, you must still provide the type argument T even though the method takes a T
parameter:
Page 92 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
do not offer the methods, properties, or members of the generic type parameters that the generic type
relies upon.
After applying a constraint you get IntelliSense reflecting the constraints when using the generic type
parameter, such as suggesting methods or members from the base type.
Derivation constraint indicates to the compiler that the generic type parameters derives from a base
type such an interface or a particular base class. For example, in the following example, the linked list
applies a constraint of deriving from IComparable<T> on its generic type parameter. This is required
so that you could implement a search. sorting or indexing functionality on the list:
class Node<K,T>
{
public K Key;
public T Item;
public Node<K,T> NextNode;
}
Page 93 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
You can provide constraints for every generic type parameter that your class declares, for example:
You can have a base class constraint, meaning, stipulating that the generic type parameter derives
from a particular base class:
However, you can only use one base class at most in a constraint because neither C#, Visual Basic or
managed C++ support multiple inheritance of implementation. Obviously, the base class you
constrain to cannot be a sealed class, and the compiler enforces that. In addition, you cannot constrain
[Link] or [Link] as a base class.
You can constrain both a base class and one or more interfaces, but the base class must appear first in
the derivation constraint list:
The constructor constraint indicates to the compiler that the generic type parameter exposes a default
public constructor (a public constructor with no parameters). For example:
public Node()
{
Key = new K(); //Compiles because of the constraint
Item = new T(); //Compiles because of the constraint
NextNode = null;
}
//Rest of the implementation
Page 94 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
You can combine the default constructor constraint with derivation constraints, provided the default
constructor constraint appears last in the constraint list:
The reference and value type constraint is used to constrain the generic type parameter to be a value
or a reference type. For example, you can constrain a generic type parameter to be a value type (such
as an int, a bool, and enum, or any structure):
{...}
Similarly, you can constrain a generic type parameter to be a reference type (a class):
{...}
The reference and value type constraint cThe value/reference type constraint cannot be used with a
base class constraint, but it can be combined with any other constraint. When used, the
value/reference type constraint must appear first in the constraint list.
It is important to note that although constraints are optional, they are often essential when developing
a generic type. Without constraints, the compiler follows the more conservative, type-safe approach
and only allows access to object-level functionality in your generic type parameters. Constraints are
part of the generic type metadata so that the client-side compiler can take advantage of them as well.
The client-side compiler only allows the client developer to use types that comply with the constraints,
thus enforcing type safety.
Page 95 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
Why Can I Not Use Enums, Structs, or Sealed Classes as Generic Constraints?
You cannot constraint a generic type parameter to derive from a non-derivable type. For example, the
following does not compile:
The reason is simple: The only type arguments that could possibly satisfy the above constraint is the
type MySealedClass itself, making the use of generics redundant. For this very reason, all other non-
derivable types such as structures and enums are not allowed in constraints.
Is Code that Uses Generics Faster than Code that Does Not?
The answer depends on the way the non-generic code is written. If the code is using objects as the
amorphous containers to store items, then various benchmarks have shown that in intense calling
patterns, generics yield on average 100 percent performance improvement (that is, three times as
fast) when using value types, and some 50 percent performance improvement when using reference
types.
If the non-generic code is using type-specific data structures, then there is no performance benefit to
generics. However, such code is inherently very fragile. Writing a type-specific data structure is a
tedious, repetitive, and error-prone task. When you fix a defect in the data structure, you have to fix it
not just in one place, but in as many places as there are type-specific duplicates of what essentially is
the same data structure.
What Is the Difference Between Using Generics and Using Interfaces (or
Abstract Classes)?
Interfaces and generics serve different purposes. Interfaces are about defining a contract between a
service consumer and a service provider. As long as the consumer programs strictly against the
interface (and not a particular implementation of it), it can use any other service provider that
supports the same interface. This allows switching service providers without affecting (or with
minimum effect on) the client's code. The interface also allows the same service provider to provide
services to different clients. Interfaces are the cornerstone of modern software engineering, and are
used extensively in past and future technologies, from COM to .NET to Indigo and SOA.
Generics are about defining and implementing a service without committing to the actual types used.
As such, interfaces and generics are not mutually exclusive. Far from it, they compliment each other.
You can and you should combine interfaces and generics.
Page 96 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
You can now program against ILinkedList<T>, using both different implementations and different type
arguments:
The client-side compiler uses that generic metadata to support type safety. When the client provides a
type arguments, the client's compiler substitutes the generic type parameter in the server metadata
with the specified type. This provides the client's compiler with type-specific definition of the server, as
if generics were never involved. At run time, the actual machine code produced depends on whether
the specified types are value or reference type. If the client specifies a value type, the JIT compiler
replaces the generic type parameters in the IL with the specific value type, and compiles it to native
code. However, the JIT compiler keeps track of type-specific server code it already generated. If the JIT
compiler is asked to compile the generic server with a value type it has already compiled to machine
code, it simply returns a reference to that server code. Because the JIT compiler uses the same value-
type-specific server code in all further encounters, there is no code bloating.
If the client specifies a reference type, then the JIT compiler replaces the generic parameters in the
server IL with object, and compiles it into native code. That code will be used in any further requests
for a reference type instead of a generic type parameter. Note that this way the JIT compiler only
reuses actual code. Instances are still allocated according to their size off the managed heap, and
there is no casting.
Page 97 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
class Node<K,T>
{
public K Key;
public T Item;
public Node<K,T> NextNode;
}
Because it has no way of knowing whether the type the consumer will specify will support the ==
operator.
class MyOtherClass
{
public static MyOtherClass operator+(MyOtherClass lhs,MyOtherClass
rhs)
{
MyOtherClass product = new MyOtherClass();
product.m_Number = lhs.m_Number + rhs.m_Number;
return product;
}
int m_Number;
//Rest of the class
}
Page 98 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
However, nothing prevents you from using generics internally, inside the attribute's implementation.
Collections
What is the difference between IEnumerator and IEnumerable? Why do we
need to use it?
The IEnumerable interface contains an abstract member function called
GetEnumerator() and return an interface IEnumerator on any success call. This
IEnumerator interface will allow us to iterate through any custom collection.
Presumably, any element in a collection can be retrieved through its index property.
But instead of element index, the IEnumerator provides two abstract methods and a
property to pull a particular element in a collection. And they are Reset(), MoveNext()
and Current.
Page 99 of 209
C# and .NET 2.0/3.5/4.0 Interview Questions
IEnumerator allows foreach style sequential access to the items in the list, using the
yield keyword. An object implementing IEnumerable allows itself to visit each of its
items through an enumerator. An object implementing IEnumerator is the doing the
iteration. It's looping over an enumerable object.
Before foreach implementation (in Java 1.4, for example), the way to iterate a list was
to get an enumerator from the list, then ask it for the "next" item in the list, for as long
as the value returned as the next item is not null. Foreach simply does that implicitly
as a language feature, in the same way that lock() implements the Monitor class
behind the scenes.
Example:
Inheriting from IEnumerable means your class returns an IEnumerator object:
So this DateRange could be useful on its own, but we want to be able to iterate this
collection using a foreach. So to start we need to implement the
IEnumerable<DateTime> interface.
IEnumerator [Link]()
{
return GetEnumerator();
}
Notice here that we now need to get the IEnumerator<DateTime> object in the
GetEnumerator() method. I jumped the gun a bit and I’ve called a class that doesn’t
exist yet. I’ll make another class and implement the required methods for the
IEnumerator interface.
object [Link]
{
get { return Current; }
}
}
10/20/2009
10/21/2009
10/22/2009
10/23/2009
10/24/2009
10/25/2009
10/26/2009
The reason is backwards compatability with .NET 1.0/1.1 which didn't support generics.
There are two interfaces because one says, "You can enumerate me," while the other
says, "here's an object that keeps track of a given enumeration task."
IEnumerable implies that the object is a collection or source of data which can be
iterated over in a linear fashion. IEnumerator is the interface for the actual
implementation which performs the iteration.
An iterator is a method, get accessor or operator that enables you to support foreach
iteration in a class or struct without having to implement the entire IEnumerable inter-
face. Instead, you provide just an iterator, which simply traverses the data structures in
your class. When the compiler detects your iterator, it will automatically generate the
Current, MoveNext and Dispose methods of the IEnumerable or IEnumerable<T> in-
terface.
Iterators Overview
An iterator is a section of code that returns an ordered sequence of values of
the same type.
An iterator can be used as the body of a method, an operator, or a get acces-
sor.
The iterator code uses the yield return statement to return each element in
turn. yield break ends the iteration.
Multiple iterators can be implemented on a class. Each iterator must have a
unique name just like any class member, and can be invoked by client code in a
foreach statement as follows: foreach(int x in SampleClass.Iterator2){}
The return type of an iterator must be IEnumerable, IEnumerator, IEnumer-
able<T>, or IEnumerator<T>.
The yield keyword is used to specify the value, or values, returned. When the yield re-
turn statement is reached, the current location is stored. Execution is restarted from
this location the next time the iterator is called.
Iterators are especially useful with collection classes, providing an easy way to iterate
non-trivial data structures such as binary trees.
Example:
In this example, the class DaysOfTheWeek is a simple collection class that stores the
days of the week as strings. After each iteration of a foreach loop, the next string in
the collection is returned.
class TestDaysOfTheWeek
{
static void Main()
{
// Create an instance of the collection class
DaysOfTheWeek week = new DaysOfTheWeek();
The cases where you might need to create a custom collection are:
In order to encapsulate logic/functionality that you wish to reuse in multiple
places in client code, in a single place instead of having to repeat it everywhere.
Say you have a need to represent collections of Invoices. List<Invoice> will do
it, but if you need only the overdue Invoices in two or three places in one
module, and only the invoices for a a specified state in another module, and
only a specific customer's invoices in a billing moodule, and let's say you need
to find and extract a specific invoice by it's Invoice Number in several places in
code. Well if all you have is List<Invoice> all the functionality to do what I
described would have to be repeated in every place in client code where you
wanted to perform those functions... If you encapsulate this functionality in a
custom collection class, you only write it once, and maintain it in one and only
place, and access it from anywhere through the collection class methods on the
instance...
Which collection would you use when you want additions, removals, and
lookups to be very quick, and when you are not concerned about the order of
the items in the collections?
[Link]<TKey, TValue> (or if you’re using the .NET
Framework 1.x, a Hashtable). The three basic operations (Add, Remove, and Contains)
all operate quickly even if the collection contains millions of items. On the other hand,
with a List<T> (or ArrayList in the .NET Framework 1.x), inserting and removing items
can take a variable amount of time. (Both List<T> and ArrayList store items in an
underlying array that maintains order. Adding items may require existing items in the
underlying array be moved to make room. Adding items at the end will not require any
moves and will be very quick).
If your usage pattern requires few deletions and mostly additions, and if it is
important for you to keep the collection in order, which collection would you
choose?
You may choose a List<T>. Lookup could be slow (since the underlying array will need
to be traversed while searching for the target item), but you are guaranteed that your
collection maintains a specific order. Alternatively, you can choose Queue<T> to
implement a first-in-first-out (FIFO) order or a Stack<T> to implement a last-in-first-out
(LIFO) order. While both Queue<T> and Stack<T> support enumeration of all items in
the collection, the former only supports insertion at the end and removal from the
beginning, while the latter only supports insertion and removal from the beginning.
namespace [Link] {
public class ProductCollection : CollectionBase {
public ProductCollection() {
}
//A useful addition to this collection class is a FindByID() method for finding specific
items in the //collection by passing an item ID, as follows:
public Product FindByID(int ID) {
foreach(Product item in List) {
if([Link] == ID) {
return item;
}
}
return null;
}
{
public void Add(string st)
{
Double d;
if ([Link](st, out d)) [Link](d);
else throw new ArgumentException(
“Cannot parse string to a double. “ +
“Item was not added to collection.”);
}
}
The .NET Framework 3.5 with its introduction of extension methods provides an
additional mechanism for creating methods that extend existing types. For example,
you could rewrite this method as an extension method in C# 3.0 as follows:
class CollectionExtensions
{
public static void Add(this Collection<Double> c, string st)
{
Double d;
if ([Link](st, out d)) [Link](d);
else throw new ArgumentException(
“Cannot parse string to a double. “ +
“Item was not added to collection.”);
}
}
Given a Collection<Double> that holds named values, this static method can be used
to add a new value to the collection using traditional syntax:
[Link](values, “3.14”);
However, as this is an extension method (evident from the "this" keyword attributing
the first parameter to the static Add method), you can rewrite this as follows:
[Link](“3.14”);
This is the exact same method call you would write if you’d extended
Collection<Double> with a new type, but you can now use this new Add method with
any instance of Collection<Double> (or any type that derives from it), rather than just
with your custom type. Alternatively, you can start building your own collection without
inheriting from any of the existing ones. In that case you can take advantage of the
appropriate interfaces that are provided in the .NET Framework.
IEnumerator<T>
ICollection
ICollection<T>
IList and IList<T>
IDictionary and IDictionary<TKey, TValue>
The comparison in the method is different depending on the data type of the value that
is being compared. [Link] is used in this example because the property that
is chosen for the comparison is a string.
The second step is to declare a method that returns an instance of your IComparer
object:
public static IComparer sortYearAscending()
{
return (IComparer) new sortYearAscendingHelper();
}
In this example, the object is used as the second argument when you call the
overloaded [Link] method that accepts IComparer. The use of IComparer is not
limited to arrays. It is accepted as an argument in a number of different collection and
control classes.
using System;
using [Link];
namespace ConsoleEnum
{
public class car : IComparable
{
// Beginning of nested classes.
else
return 0;
}
}
else
return 0;
}
}
{
return (IComparer) new sortYearAscendingHelper();
}
}
}
using System;
namespace ConsoleEnum
{
class host
{
[STAThread]
static void Main(string[] args)
{
// Create an arary of car objects.
car[] arrayOfCars= new car[6]
{
new car("Ford",1992),
new car("Fiat",1988),
new car("Buick",1932),
new car("Ford",1932),
new car("Dodge",1999),
new car("Honda",1977)
};
foreach(car c in arrayOfCars)
[Link]([Link] + "\t\t" + [Link]);
foreach(car c in arrayOfCars)
[Link]([Link] + "\t\t" + [Link]);
foreach(car c in arrayOfCars)
[Link]([Link] + "\t\t" + [Link]);
foreach(car c in arrayOfCars)
[Link]([Link] + "\t\t" + [Link]);
foreach(car c in arrayOfCars)
[Link]([Link] + "\t\t" + [Link]);
[Link]();
}
}
}
For example we have a simple Employee class with two fields, Name and
Salary.
class Employee
{
public string Name { get; set; }
public int Salary { get; set; }
}
Now create a List of Employees and call Sort() method of a List.
Example
Output
11
22
33
Example
using System;
using [Link];
class Test
{
static void Main()
{
Stack stack = new Stack();
[Link](2);
[Link](4);
[Link](6);
while([Link] != 0)
{
[Link]([Link]());
}
}
}
Output
6
4
2
A collection that works on the First In First Out (FIFO) principle, i.e.,
the first item inserted is the first item removed from the collection.
Enqueue - To add element and Dequeue – To Remove element
Example:
while([Link] != 0)
{
[Link]([Link]());
}
}
Output
2
4
6
Example:
static void Main()
{
Hashtable ht = new Hashtable(20);
[Link]("ht01", "DotNetGuts");
[Link]("ht02", "[Link]");
[Link]("ht03", "[Link]");
[Link]("Printing Keys...");
foreach(string key in [Link])
{
[Link](key);
}
[Link]("\nPrinting Values...");
foreach(string Value in [Link])
{
[Link](Value);
}
[Link]([Link]("ht01"));
[Link]([Link]("[Link]"));
Output
Printing Keys...
ht01
ht02
ht03
Printing Values...
DotNetGuts
[Link]
[Link]
Size of Hashtable is 3
True
True
Probably, all of the keys will be put into a single bucket. Therefore, when a lookup is
performed, the .NET runtime will be forced to traverse the entire contents of that
bucket to find the value. So, instead of the lookup operation being O(1), the average
lookup case becomes O(n).
To alleviate this problem, override the GetHashCode method; so, the runtime can
access the keys efficiently.
One way to address the problem is to create a key string by merging all the value
types from a struct. Each type is seperated by a special delimiter character. Since the
struct is a lookup criteria, it is certain that all struct values will be different; therefore,
the generated string is guaranteed to be unique. And, since the string is derived from
[Link], the generated key string has a GetHashCode method which can be
overridden.
Here is an example of overriding the GetHashCode method:
struct
{
int value-a;
short value-b;
[Link]-a = value-a;
[Link]-b = value-b;
}
What’s the .NET collection class that allows an element to be accessed using
a unique key?
HashTable.
A Hashtable object consists of buckets that contain the elements of the collection. A
bucket is a virtual subgroup of elements within the Hashtable, which makes searching
and retrieving easier and faster than in most collections. Each bucket is associated
with a hash code, generated using a hash function and based on the key of the
element.
A hash function is an algorithm that returns a numeric hash code based on a key. The
key is the value of some property of the object being stored. A hash function must
always return the same hash code for the same key. It is possible for a hash function to
generate the same hash code for two different keys, but a hash function that generates
a unique hash code for each unique key results in better performance when retrieving
elements from the hash table.
searched for in the Hashtable, the hash code is generated for that value, and the
bucket associated with that hash code is searched.
For example, a hash function for a string might take the ASCII codes of each character
in the string and add them together to generate a hash code. The string "picnic" would
have a hash code that is different from the hash code for the string "basket"; therefore,
the strings "picnic" and "basket" would be in different buckets. In contrast, "stressed"
and "desserts" would have the same hash code and would be in the same bucket.
The Dictionary class has the same functionality as the Hashtable class. A Dictionary
of a specific type (other than Object) has better performance than a Hashtable for
value types because the elements of Hashtable are of type Object and, therefore,
boxing and unboxing typically occur if storing or retrieving a value type.
Output
Key Value
==
1 C++.Net
5 C#
11 [Link]
18 Java
*******************************************************************
CLR facilities
Exceptions
Automatic Memory Management
CLR Hosting and Appdomains
Thread synchronization
Exceptions
What is an Exception?
An exception is an abnormal condition that arises in a code sequence at run time. In
other words, an exception is a run-time error.
Exceptions are the standard mechanism for reporting errors. Applications and libraries
should not use return codes to communicate errors. The use of exceptions adds to a
consistent framework design and allows error reporting from members, such as
constructors, that cannot have a return type. Exceptions also allow programs to handle
the error or terminate as appropriate. The default behavior is to terminate an
application if it does not handle a thrown exception.
Throw some light on error and exception handling. What are the differences?
Error handling refers to the anticipation, detection, and resolution of programming,
application, and communications errors. Specialized programs, called error handlers,
are available for some applications. The best programs of this type forestall errors if
possible, recover from them when they occur without terminating the application, or (if
all else fails) gracefully terminate an affected application and save the error
information to a log file.
In programming, a development error is one that can be prevented. Such an error can
occur in syntax or logic. Syntax errors, which are typographical mistakes or improper
use of special characters, are handled by rigorous proofreading. Logic errors, also
called bugs, occur when executed code does not produce the expected or desired
result. Logic errors are best handled by meticulous program debugging. This can be
an ongoing process that involves, in addition to the traditional debugging routine,
beta testing prior to official release and customer feedback after official release.
A run-time error takes place during the execution of a program, and usually happens
because of adverse system parameters or invalid input data. An example is the lack
of sufficient memory to run an application or a memory conflict with another
program. On the Internet, run-time errors can result from electrical noise, various
forms of malware or an exceptionally heavy demand on a server. Run-time errors can
be resolved, or their impact minimized, by the use of error handler programs, by
vigilance on the part of network and server administrators, and by reasonable security.
The code in finally block is guaranteed to run, irrespective of whether an error occurs
or not. Critical portions of code, for example release of file handles or database
connections, should be placed in the finally block.
Will the finally block get executed if an exception has not occurred?
Yes.
Well, if at that point you know that an error has occurred, then why not write the
proper code to handle that error instead of passing a new Exception object to the catch
block? Throwing your own exceptions signifies some design flaws in the project.
A catch block that catches the exception of type [Link]. You can also omit
the parameter data type in this case and just write catch {}
call, but a straightforward example of an expected error is failing to read from a file
because the seek pointer is at the end of the file, whereas an example of an
unexpected error is failing to allocate memory from the heap.
Answer:
Use try...catch block to catch exceptions.
To catch all exception use base Exception class "Exception"
try
{
}
catch(Exception)
{
index that is less than zero or outside the bounds of the array.
[Link] Thrown when an attempt to combine two non-
null delegates fails, because the delegate type does not have a void return type.
[Link] A base class for exceptions that occur during arithmetic
operations, such as DivideByZeroException and OverflowException.
[Link] Thrown when an attempt to divide an integral value by
zero occurs.
[Link] Thrown when an arithmetic operation in a checked context
overflows.
If I return out of a try/finally in C#, does the code in the finally-clause run?
Yes. The code in the finally always runs. If you return out of the try block, or even if you
do a “goto” out of the try, the finally block always runs:
using System;
class main
{
public static void Main()
{
try
{
[Link]("In Try block");
return;
}
finally
{
[Link]("In Finally block");
}
}
}
Both “In Try block” and “In Finally block” will be displayed. Whether the return is in the
try block or after the try-finally block, performance is not affected either way. The
compiler treats it as if the return were outside the try block anyway. If it’s a return
without an expression (as it is above), the IL emitted is identical whether the return is
inside or outside of the try. If the return has an expression, there’s an extra store/load
of the value of the expression (since it has to be computed within the try block).
If we write return statement in finally block will it works fine or throws any
error?
NO. We cannot have return in finally block. We get the following error.
“Control cannot leave the body of a finally clause”.
try
{
First.DoSomething1();
First.DoSomething2();
}
catch (Exception)
{
throw;
}
finally { return 0; }
Which return will get invoked when exception occurs in try block and when
exception does not occur?
try
{
First.DoSomething1();
First.DoSomething2();
return 1;
}
catch (Exception)
{
return 2;
}
finally { }
When exception is thrown, return 2 will get invoked and when exception is not thrown,
return 1 would get invoked.
The following guidelines help ensure that your custom exceptions are correctly
designed.
Avoid deep exception hierarchies.
Do derive exceptions from [Link] or one of the other common base
exceptions.
Note that Catching and Throwing Standard Exception Types has a guideline that
states that you should not derive custom exceptions from ApplicationException.
Do end exception class names with the Exception suffix.
Do make exceptions serializable. An exception must be serializable to work
correctly across application domain and remoting boundaries.
Do provide (at least) the following common constructors on all exceptions. Make
sure the names and types of the parameters are the same those used in the
following code example.
public class NewException : BaseException, ISerializable
{
public NewException()
{
// Add implementation.
}
public NewException(string message)
{
// Add implementation.
}
public NewException(string message, Exception inner)
{
// Add implementation.
}
inconvenient. For example, if you were unable to fully initialize the object, for example
because of inconsistent or corrupt state, you would have no other choice but to throw
an exception. The alternative would be to pretend everything was OK by returning
successfully from the constructor, which could lead to failures later on in the program’s
execution. It’s better just to have the program fail as soon as you notice a problem.
The reason that this topic is problematic enough to call out is that, in the face of an
exception thrown by a constructor, the caller of your constructor will have no reference
to your object. Consider what the IL sequence looks like for the C# code Foo f = new
Foo():
The newobj instruction makes a call to the constructor, leaving the result on the
execution stack. stloc.0 stores it in a local slot in the execution stack. But if an
exception is raised as a result of the newobj instruction (because of insufficient
memory to allocate the object, or because of an unhandled exception thrown from the
constructor), the result will never be placed on the stack, and the stloc.0 will never
execute because the CLR exception handling behavior will take over. The result is that
the variable f will be null.
This can cause some unpredictable behavior. For example, consider a type that
allocates resources in its constructor but then throws an exception. Normally, types
like this will support the IDisposable interface—explained fully in Chapter 5—so that
these resources can be reclaimed deterministically. Such code might look like this:
The semantics of the using statement are such that the variable inside the parenthesis
will have its Dispose method called at the end of the block, regardless of whether exit
is normal or due to an exception from the block’s body. But if an exception occurs
during the call to Foo’s constructor, f will never get assigned a value! The result is that
Dispose will never get called, and hopefully f’s finalizer will clean up the resources
sometime later on.
Constructors do not have return type and so they cannot return error codes
(of course possible with out or ref parameter, but it is not recommended to
use out or ref parameter). How are errors or exceptions handled in
constructors? What if the calls that you make in the constructor can actually
throw exceptions? How do you let the caller know something bad happened
in a constructor? Or, How to let the invoker know that the instance of the
object has not been created successfully, so that the invoker can perform
appropriate actions?
1. Do as little in the constructor has you can. Then provide an Init() function in the
constructor, which does the normal initialization stuff. The user can then call
this function after creating an object. The problem here is, its up to the user to
actually call the Init() function. The user could potentially miss this step, making
this method error prone. However, there are a lot of places where this method-
ology is used. You are trying to eliminate error handling in the constructor by
using this method
2. Another way to do this is by putting the object in a Zombie state. This is one ap-
proach you can take especially if you do not have the option of using excep-
tions. When you go with this option, you will also to do provide a function that
will check the state of the object after construction. The downsides to this op-
tion is that, its up to the user to do these checks and the users will need to do
this every time one attempts to create an object. It’s usually always better and
cleaner to throw an exception instead. Use the Zombie option as a last resort.
3. The downsides to the above methods can be reduced by making the constructor
private or protected, expose a CreateInstance() public method, and do all the
error handling here rather than leave it to the user. But sometimes, it’s not pos-
sible to handle all the error conditions in a generic manner and you will need to
throw an exception.
4. If an exception is thrown in the constructor, the destructor will not get called. So
you need to handle and clean up as much as you can before you leave the con-
structor. The best way to do this is using the “resource allocation is initializa-
tion” technique in C++. But the basic idea is to assign resource allocation and
cleanup to other objects. Basically, you are trying to get allocation out of the
way (indirect) so that you don’t have to do it explicitly. When you don’t allocate
something directly, you don’t have to release it either because it will be done by
the component or class who deals with it. E.g. If you need to allocate some
memory or open up a file, You can use smart objects (smart pointer, auto_ptr,
smart file handlers etc..) instead of calling new or fopen directly. When you do
this, and if an exception is thrown in your constructor, the smart objects will au-
tomatically release the resources it acquired, as the stack unwinds. If you do
not use the “resource allocation is initialization” technique (in java and C#), the
user will need to wrap the statements in try/catch block and re-throw after
cleaning up the mess, something like what the finally block does in Java or C#.
Although this works in theory, it’s up to the user to make this work and it also
always a source of errors and bugs (esp. memory and handle leaks) and is
messy.
As you have seen, there is no “one size fits all” rule to do error/exception handling in
constructors. I have listed the most commonly used methods and one of these should
work most of the time.
How can one report errors to invoker of constructor using error code?
There is a more clean solution to the problem. Constructors, as any other methods, can
return many values to the calling program via “ref” parameters! It would be natural for
constructors to validate their arguments and report errors. So here is solution:
class Levels
{
Attributes
How do you specify a custom attribute for the entire assembly (rather than
for a class)? - Global attributes must appear after any top-level using clauses and
before the first type or namespace declarations. An example of this is as follows:
using System;
or
Application domain is the boundary within which an application runs. A process can
contain multiple application domains. Application domains provide an isolated
environment to applications that is similar to the isolation provided by processes. An
application running inside one application domain cannot directly access the code
running inside another application domain. To access the code running in another
application domain, an application needs to use a proxy.
AppDomains are usually created by hosts. Examples of hosts are the Windows Shell,
[Link] and IE. When you run a .NET application from the command-line, the host is
the Shell. The Shell creates a new AppDomain for every application.
AppDomains can also be explicitly created by .NET applications. Here is a C# sample
which creates an AppDomain, creates an instance of an object inside it, and then
executes one of the object's methods:
using System;
using [Link];
using [Link];
Serialization is the process of converting an object into a stream of bytes. Deserialization is the opposite
process, i.e. creating an object from a stream of bytes.
There are two separate mechanisms provided by the .NET class library - XmlSerializer and
SoapFormatter/BinaryFormatter. Microsoft uses XmlSerializer for Web Services, and
SoapFormatter/BinaryFormatter for remoting. Both are available for use in your own code.
It depends. XmlSerializer has severe limitations such as the requirement that the target class has a
parameterless constructor, and only public read/write properties and fields can be serialized. However,
on the plus side, XmlSerializer has good support for customising the XML document that is produced or
consumed. XmlSerializer's features mean that it is most suitable for cross-platform work, or for
constructing objects from existing XML documents.
SoapFormatter and BinaryFormatter have fewer limitations than XmlSerializer. They can serialize private
fields, for example. However they both require that the target class be marked with the [Serializable]
attribute, so like XmlSerializer the class needs to be written with serialization in mind. Also there are
some quirks to watch out for - for example on deserialization the constructor of the new object is not
invoked.
The choice between SoapFormatter and BinaryFormatter depends on the application. BinaryFormatter
makes sense where both serialization and deserialization will be performed on the .NET platform and
where performance is important. SoapFormatter generally makes more sense in all other cases, for ease
of debugging if nothing else.
Yes. XmlSerializer supports a range of attributes that can be used to configure serialization for a
particular class. For example, a field or property can be marked with the [XmlIgnore] attribute to exclude
it from serialization. Another example is the [XmlElement] attribute, which can be used to specify the
XML element name to be used for a particular property or field.
Serialization via SoapFormatter/BinaryFormatter can also be controlled to some extent by attributes. For
example, the [NonSerialized] attribute is the equivalent of XmlSerializer's [XmlIgnore] attribute. Ultimate
control of the serialization process can be acheived by implementing the the ISerializable interface on
the class whose instances are to be serialized.
There is a once-per-process-per-type overhead with XmlSerializer. So the first time you serialize or
deserialize an object of a given type in an application, there is a significant delay. This normally doesn't
matter, but it may mean, for example, that XmlSerializer is a poor choice for loading configuration
settings during startup of a GUI application.
XmlSerializer will refuse to serialize instances of any class that implements IDictionary, e.g. Hashtable.
SoapFormatter and BinaryFormatter do not have this restriction.
XmlSerializer is throwing a generic "There was an error reflecting MyClass" error. How
do I find out what the problem is?
Look at the InnerException property of the exception that is thrown to get a more specific error message.
XmlSerializer needs to know in advance what type of objects it will find in an ArrayList. To specify the
type, use the XmlArrayItem attibute like this:
{
[XmlArrayItem(typeof(Person))] public ArrayList People;
}
1. Which class is responsible for binary serialization?
The BinaryFormater is the class responsible for the binary serialization and It's commonly used for
the .Net Remoting.
Your class must have the attribute SerializableAttribute and all its members must also be
serializable, except if they are ignored with the attribute NonSerializedAttribute. Private and public
fields are serialized by default.
[Serializable]
public class Invoice {
private string clientName;
private DateTime date;
private double total;
[NonSerialized]
private string internalCode;
Yes if the properties encapsulate a field. By default all the private and public fields are serialized.
Binary serialization is not related to properties.
Yes it is, you can have circular reference and the binary serialization process will work fine. .Net
generate the object graph before the executing the serialization and finally generate the stream.
Unlike Xml serialization process, the BinaryFormater has no problem with the circular reference.
By default the DataSet is serialized in Xml and the binary stream only wraps the Xml Data inside it.
That's mean that the size is similar to the Xml size. .Net 2.0 add a new property named
RemotingFormat used to change the binary serialization format of the DataSet.
[Link] will generate a better result.
For previous version, it's also possible to download the DataSetSurrogate to reduce the size and
increase the performance.
If you need to control the serialization process of your class, you can implement the ISerializable
interface which contains a method GetObjectData and a special constructor . Why use custom
serialization ? By using it you will be able to handle version change in your class or get a better
performance result. An exception of type SerializationException is raised if the fields does not
exists.
//Special constructor
protected CustomInvoice(SerializationInfo info, StreamingContext context) {
clientName = [Link]("clientName");
date = [Link]("date");
total = [Link]("total");
}
[SecurityPermissionAttribute([Link], SerializationFormatter =
true)]
public void GetObjectData(SerializationInfo info, StreamingContext context) {
[Link]("clientName", clientName);
[Link]("date", date);
[Link]("total", total);
}
#endregion
Binary serialization is not tolerant to version change. There is no problem when a new field is added
but if a field is missing, an exception is throw. New field will get the default value. .Net 2.0 include a
new attribute named OptionalFieldAttribute. For previous version, you must implement your own
custom serialization and handle manually the changes.
Version fault exception are only checked if the assembly is signed, all version change are ignored
otherwise.
Use the OptionalFieldAttribute or implement your own custom serialization with ISerializable.
The parameter is only for informative purpose. .Net never checked it by default but it could be used
in a custom serialization. Use the reflection to get the attribute of field and check the added version
value.
15. Does BinaryFormatter from .Net 1.1 is compatible with the BinaryFormatter 2.0?
Absolutely, the BinaryFormatter 2.0 is 100% with other version, but it's not the case with the
SoapFormatter.
16. How can I modify a value just before the serialization or just after the
deserialization?
You can add custom attribute to some method. Your marked method will get called a the right time.
This is usefull to initialize a property after the deserialization or to clean up your instance before the
serialization.
[Serializable]
public class SecurityToken {
private string password;
private string userName;
[OnSerializing()]
internal void OnSerializingMethod(StreamingContext context) {
password = Encrypt(password);
[OnDeserialized()]
internal void OnDeserializedMethod(StreamingContext context) {
password = Decrypt(password);
SoapFormatter is used to create a Soap envelop and use an object graph to generate the result.
The XmlSerializer process use only the public data and the result is a more common xml file. The
Web Service in .Net use an XmlSerializer to generate the output contained in the Soap message.
The SoapFormatter and the BinaryFormatter are used in the .Net Remoting serialization process.
If you use a XmlSerializer, mark your property with the custom attribute XmlIgnoreAttribute and if
you use a SoapFormatter, use a SoapIgnoreAttribute instead.
Use the attribute XmlElementAttribute or XmlAttributeAttribute with the new name as parameter.
To rename a class, use the XmlTypeAttribute.
[XmlType("city")]
public class Town {
private string name;
private string state;
[XmlElement("townname")]
public string Name {
get {
return name;
}
set {
name = value;
}
}
[XmlAttribute("state")]
public string State {
get {
return state;
}
set {
state = value;
}
}
}
Result:
<?xml version="1.0"?>
<city state="CA">
<townname>Los Angeles</townname>
</city>
10. How can I read a field from an Xml stream without deserializing it?
XPath can do the job.. This is an example where we read the town name (Xml element) )and the
state attribute from the Xml file:
//Select an element
string _TownName = [Link]("//city/townname").InnerText;
//Select an attribute
string _State =
[Link]("//city").Attributes["state"].InnerText;
This is an example where we read an application setting from a web config file.
<configuration xmlns="[Link]
<appSettings>
<add key="DatabaseName" value="Pubs"/>
<add key="DatabaseServer" value="(local)"/>
</appSettings>
</configuration>
Note, you don't need the XmlNamespaceManager if you don't have a default namespace.
[Link] in the ealier version does not contain a default namespace.
11. How can I serialize a property as an Xml attribute?
By default properties are serialized as Xml elements, but if you add an XmlAttributeAttribute to a
property, .Net will generate an attribute instead. It's must be type compatible with an Xml attribute.
See example here
...
[XmlAttribute("state")]
public string State {
get {
return state;
}
set {
state = value;
}
}
You need to Implement the interface IXmlSerializable. This class is available in the .Net 1.X but it's
was not documented. It's now official available with .Net 2.0. With custom serialization, it's possible
to optimize the output and generate only what is needed. In this example, we generate only the non
empty properties
while ([Link]()) {
if ([Link]()) {
if (![Link]) {
string _ElementName = [Link];
[Link](); // Read the start tag.
if(_ElementName == "MachineName") {
MachineName = [Link]();
} else {
[Link]();
}
}
}
}
}
if ()
[Link]("MachineName", MachineName);
}
#endregion
The output could be something like that if UserName and Machine are not empty :
<?xml version="1.0"?>
<SessionInfo UserName="David">
<MachineName>MyMachine</MachineName>
</SessionInfo>
<?xml version="1.0"?>
<SessionInfo UserName="David">
Array are compatible with the serialization, but all elements must be of the same type. If not all types
must be specified, see below.
It's possible to tag the array with all the possible type. Use XmlInclude on the class containing the
array or XmlArrayItem. All the possible types must be specified with the attributes. Array types
must be known because of the Xml schema. XmlInclude could be used for property that returned
differente types. It's complicate object inheritance since all types must be known.
This example will fail with a message "There was an error generating the XML document." because
the Cars could contain undefined types.
...
Ford _Ford = new Ford();
Honda _Honda = new Honda();
Toyota _Toyota = new Toyota();
[Link](_Seller, @"[Link]");
[XmlInclude(typeof(Ford))]
[XmlInclude(typeof(Honda))]
[XmlInclude(typeof(Toyota))]
public class CarSeller {
<?xml version="1.0"?>
<CarSeller>
<Cars>
<Car xsi:type="Ford" />
<Car xsi:type="Honda" />
<Car xsi:type="Toyota" />
</Cars>
</CarSeller>
[XmlArrayItem(typeof(Ford))]
[XmlArrayItem(typeof(Honda))]
[XmlArrayItem(typeof(Toyota))]
public List<Car> Cars {
get {
return cars;
}
set {
cars = value;
}
}
}
<?xml version="1.0"?>
<CarSeller>
<Cars>
<Ford />
<Honda />
<Toyota />
</Cars>
</CarSeller>
Collection are serialized correctly, but they must contains only object of same types. Read only
properties of type ArrayList, List<type> and other collections will be serialized and deserialized
correctly.
// Generic version
private List<Role> roles = new List<Role>();
// ArrayList version
private ArrayList roleList = new ArrayList();
_UserAccount.[Link](_RoleAdmin);
_UserAccount.[Link](_RoleSales);
_UserAccount.[Link](_RoleAdmin);
_UserAccount.[Link](_RoleSales);
_UserAccount.[Link]("Admin");
_UserAccount.[Link]("Sales");
[Link](_UserAccount, @"[Link]");
UserAccount _Result =
[Link]<UserAccount>(@"[Link]");
will produce:
<?xml version="1.0"?>
<UserAccount>
<UserName>dhervieux</UserName>
<Roles>
<Role>
<Name>Admin</Name>
</Role>
<Role>
<Name>Sales</Name>
</Role>
</Roles>
<RoleList>
<anyType xsi:type="Role">
<Name>Admin</Name>
</anyType>
<anyType xsi:type="Role">
<Name>Sales</Name>
</anyType>
</RoleList>
<RoleNames>
<string>Admin</string>
<string>Sales</string>
</RoleNames>
</UserAccount>
XmlSerializer generate an assembly in memory optimized for each type. That's explain why the first
call to a Web Service is so long. In .Net 2.0, there is an option in the project properties of Visual
Studio to generate the Xml serialization assembly. Use it directly in the IDE or use [Link], this
tools come with the .Net Framework SDK.
Pregenerate your serialization assembly with Visual Studio or [Link]. See details in answer
above. Implementing your own serialization could also increase the performance.
Yes it possible. .Net will name the Array and save the content. All the data must be of the same
type.
// Serialization
[Link](_BoolArray, @"[Link]");
//Deserialization
_Result = [Link]<bool[]>(@"[Link]");
will produce:
<?xml version="1.0"?>
<ArrayOfBoolean>
<boolean>true</boolean>
<boolean>false</boolean>
<boolean>false</boolean>
<boolean>true</boolean>
</ArrayOfBoolean>
Web Services are using SOAP to communicate, but returned objets or parameters are serialized
with the XmlSerializer. Write unit test to be sure that your objects are serializable.
You need to encapsulate your array in a structure or a class an serialize it. Multidimensional array
are not serializable by default.
22. How can I avoid serialization for an empty list or property with a default value?
There is an undocumented way of doing that, you need to create a method named
ShouldSerialize<propertyname> where <propertyname> is replaced by the property name. This
method should return a boolean that indicate if the property must be serialized or not. For exemple,
if you have list with no item, there is no need to serialize an empty list.
Result :
<?xml version="1.0"?>
<Registration />
<?xml version="1.0"?>
<Registration >
<Users />
</Registration>
23. Why my object is marked as Serializable (like SortedList) and it's does not work?
The SerializationAttribute is only used for the binary serialization. That does not mean that it will
work with an XmlSerializer. That's the case of the SortedList.
Interoperability
Yes. Any COM component you have deployed today can be used from managed code,
and in common cases the adaptation is totally automatic.
Specifically, COM components are accessed from the .NET Framework by use of a
runtime callable wrapper (RCW). This wrapper turns the COM interfaces exposed by the
COM component into .NET Framework-compatible interfaces. For OLE automation
interfaces, the RCW can be generated automatically from a type library. For non-OLE
automation interfaces, a developer may write a custom RCW and manually map the
types exposed by the COM interface to .NET Framework-compatible types.
Yes. Managed types you build today can be made accessible from COM, and in the
common case the configuration is totally automatic. There are certain new features of
the managed development environment that are not accessible from COM. For
example, static methods and parameterized constructors cannot be used from COM. In
general, it is a good idea to decide in advance who the intended user of a given type
will be. If the type is to be used from COM, you may be restricted to using those
features that are COM accessible.
Depending on the language used to write the managed type, it may or may not be
visible by default.
Specifically, .NET Framework components are accessed from COM by using a COM
callable wrapper (CCW). This is similar to an RCW (see previous question), but works in
the opposite direction. Again, if the .NET Framework development tools cannot
automatically generate the wrapper, or if the automatic behavior is not what you want,
a custom CCW can be developed.
Interop Services?
The common language runtime provides two mechanisms for interoperating with
unmanaged code:
Platform invoke, which enables managed code to call functions exported from
an unmanaged library.
COM interop, which enables managed code to interact with COM objects
through interfaces.
Both platform invoke and COM interop use interop marshaling to accurately move
method arguments between caller and callee and back, if required.
A proxy object generated by the common language runtime so that existing COM
applications can use managed classes, including .NET Framework classes,
transparently.
What is the new three features of COM+ services, which are not there in COM
(MTS)?
**
What is Pinvoke?
Platform invoke is a service that enables managed code to call unmanaged functions
implemented in dynamic-link libraries (DLLs), such as those in the Win32 API. It locates
and invokes an exported function and marshals its arguments (integers, strings,
arrays, structures, and so on) across the interoperation boundary as needed.
Use the Type Library Import utility shipped with SDK. tlbimp [Link]
/out:.[Link] or reference the COM library from Visual Studio in your project.
Did you write that object? You can only import your own objects. If you need to use a
COM component from another developer, you should obtain a Primary Interop
Assembly (PIA) from whoever authored the original object.
How do you call unmanaged methods from your .NET code through PInvoke?
Supply a DllImport attribute. Declare the methods in your .NET code as static extern.
Do not implement the methods as they are implemented in your unmanaged code,
you’re just providing declarations for method signatures.
Yes. Using platform invoke, .NET Framework programs can access native code libraries
by means of static DLL entry points.
using System;
using [Link];
class MainApp
{
[DllImport("[Link]", EntryPoint="MessageBox")]
public static extern int MessageBox(int hWnd, String strMessage, String strCaption,
uint uiType);
Can you retrieve complex data types like structs from the PInvoke calls?
Yes, just make sure you re-declare that struct, so that managed code knows what to do
with it.
Yes, but few things should be considered first. Classes should implement interfaces
explicitly. Managed types must be public. Methods, properties, fields, and events that
are exposed to COM must be public. Types must have a public default constructor with
no arguments to be activated from COM. Types cannot be abstract.
The .NET Framework extends the COM model for reusability by adding implementation
inheritance. Managed types can derive directly or indirectly from a COM coclass; more
specifically, they can derive from the runtime callable wrapper generated by the
runtime. The derived type can expose all the method and properties of the COM object
as well as methods and properties implemented in managed code. The resulting object
is partly implemented in managed code and partly implemented in unmanaged code.
Suppose I call a COM object from a .NET applicaiton, but COM object throws
an error. What happens on the .NET end?
COM methods report errors by returning HRESULTs; .NET methods report them by
throwing exceptions. The runtime handles the transition between the two. Each
exception class in the .NET Framework maps to an HRESULT.
This subject causes a lot of controversy, as you'll see if you read the mailing list
archives. Take a look at the following two threads:
[Link]
[Link]
The bottom line is that .NET has its own mechanisms for type interaction, and they
don't use COM. No IUnknown, no IDL, no typelibs, no registry-based activation. This is
mostly good, as a lot of COM was ugly. Generally speaking, .NET allows you to package
and use components in a similar way to COM, but makes the whole thing a bit easier.
Is DCOM dead?
Pretty much, for .NET developers. The .NET Framework has a new remoting model
which is not based on DCOM. DCOM was pretty much dead anyway, once firewalls
became widespread and Microsoft got SOAP fever. Of course DCOM will still be used in
interop scenarios.
Is COM+ dead?
Not immediately. The approach for .NET 1.0 was to provide access to the existing
COM+ services (through an interop layer) rather than replace the services with
native .NET ones. Various tools and attributes were provided to make this as painless
as possible. Over time it is expected that interop will become more seamless - this may
mean that some services become a core part of the CLR, and/or it may mean that
some services will be rewritten as managed code which runs on top of the CLR.
For more on this topic, search for postings by Joe Long in the archives - Joe is the MS
group manager for COM+. Start with this message:
[Link]
Yes. COM components are accessed from the .NET runtime via a Runtime Callable
Wrapper (RCW). This wrapper turns the COM interfaces exposed by the COM
component into .NET-compatible interfaces. For oleautomation interfaces, the RCW can
be generated automatically from a type library. For non-oleautomation interfaces, it
may be necessary to develop a custom RCW which manually maps the types exposed
by the COM interface to .NET-compatible types.
Here's a simple example for those familiar with ATL. First, create an ATL component
which implements the following IDL:
import "[Link]";
import "[Link]";
[
object,
uuid(EA013F93-487A-4403-86EC-FD9FEE5E6206),
helpstring("ICppName Interface"),
pointer_default(unique),
oleautomation
]
[
uuid(F5E4C61D-D93A-4295-A4B4-2453D4A4484D),
version(1.0),
helpstring("cppcomserver 1.0 Type Library")
]
library CPPCOMSERVERLib
{
importlib("[Link]");
importlib("[Link]");
[
uuid(600CE6D9-5ED7-4B4D-BB49-E8D5D5096F70),
helpstring("CppName Class")
]
coclass CppName
{
[default] interface ICppName;
};
};
When you've built the component, you should get a typelibrary. Run the TLBIMP utility
on the typelibary, like this:
tlbimp [Link]
You now need a .NET client - let's use C#. Create a .cs file containing the following
code:
using System;
using CPPCOMSERVERLib;
Note that the compiler is being told to reference the DLL we previously generated from
the typelibrary using TLBIMP. You should now be able to run [Link], and
get the following output on the console:
Name is bob
Yes. .NET components are accessed from COM via a COM Callable Wrapper (CCW). This
is similar to a RCW (see previous question), but works in the opposite direction. Again,
if the wrapper cannot be automatically generated by the .NET development tools, or if
the automatic behaviour is not desirable, a custom CCW can be developed. Also, for
COM to 'see' the .NET component, the .NET component must be registered in the
registry.
Here's a simple example. Create a C# file called [Link] and put the
following in it:
using System;
using [Link];
namespace AndyMc
{
[ClassInterface([Link])]
public class CSharpCOMServer
{
public CSharpCOMServer() {}
public void SetName( string name ) { m_name = name; }
public string GetName() { return m_name; }
private string m_name;
}
}
Now you need to create a client to test your .NET COM component. VBScript will do -
put the following in a file called [Link]:
Dim dotNetObj
Set dotNetObj = CreateObject("[Link]")
[Link] ("bob")
MsgBox "Name is " & [Link]()
And hey presto you should get a message box displayed with the text "Name is bob".
An alternative to the approach above it to use the [Link] moniker developed by Jason
Whittington and Don Box.
Yes. ATL will continue to be valuable for writing COM components for some time, but it
has no place in the .NET world.
This example shows the minimum requirements for declaring a C# method that is
implemented in a native DLL. The method [Link]() is declared with the static
and external modifiers, and has the DllImport attribute, which tells the compiler that
the implementation comes from the [Link], using the default name of
MessageBoxA. For more information, look at the Platform Invoke tutorial in the
documentation.
You must use the Missing class and pass [Link] (in [Link]) for any
values that have optional parameters.
Security
What do I have to do to make my code work with the security system?
Usually, not a thing—most applications will run safely and will not be exploitable by
malicious attacks. By simply using the standard class libraries to access resources (like
files) or perform protected operations (such as a reflection on private members of a
type), security will be enforced by these libraries. The one simple thing application
developers may want to do is include a permission request (a form of declarative
security) to limit the permissions their code may receive (to only those it requires). This
also ensures that if the code is allowed to run, it will do so with all the permissions it
needs.
Only developers writing new base class libraries that expose new kinds of resources
need to work directly with the security system. Instead of all code being a potential
security risk, code access security constrains this to a very small bit of code that
explicitly overrides the security system.
Why does my code get a security exception when I run it from a network
shared
drive?
Default security policy gives only a restricted set of permissions to code that comes
from the local intranet zone. This zone is defined by the Internet Explorer security
settings, and should be configured to match the local network within an enterprise.
Since files named by UNC or by a mapped drive (such as with the NET USE command)
are being sent over this local network, they too are in the local intranet zone.
The default is set for the worst case of an unsecured intranet. If your intranet is more
secure you can modify security policy (with the .NET Framework Configuration tool or
the CASPol tool) to grant more permissions to the local intranet, or to portions of it
(such as specific machine share names).
How do I make it so that code runs when the security system is stopping it?
Security exceptions occur when code attempts to perform actions for which it has not
been granted permission. Permissions are granted based on what is known about code;
especially its location. For example, code run from the Internet is given fewer
permissions than that run from the local machine because experience has proven that
it is generally less reliable. So, to allow code to run that is failing due to security
exceptions, you must increase the permissions granted to it. One simple way to do so
is to move the code to a more trusted location (such as the local file system). But this
won't work in all cases (web applications are a good example, and intranet applications
on a corporate network are another). So, instead of changing the code's location, you
can also change security policy to grant more permissions to that location. This is done
using either the .NET Framework Configuration tool or the code access security policy
utility ([Link]). If you are the code's developer or publisher, you may also digitally
sign it and then modify security policy to grant more permissions to code bearing that
signature. When taking any of these actions, however, remember that code is given
fewer permissions because it is not from an identifiably trustworthy source—before you
move code to your local machine or change security policy, you should be sure that
you trust the code to not perform malicious or damaging actions.
The .NET Framework includes the .NET Framework Configuration tool, an MMC snap-in
([Link]), to configure several aspects of the CLR including security policy. The
snap-in not only supports administering security policy on the local machine, but also
creates enterprise policy deployment packages compatible with System Management
Server and Group Policy. A command line utility, [Link], can also be used to script
policy changes on the computer. In order to run either tool, in a command prompt,
change the current directory to the installation directory of the .NET Framework
(located in %windir%\[Link]\Framework\v1.0.2914.16\) and type [Link]
or [Link].
Evidence-based security (which authorizes code) works together with Windows 2000
security (which is based on log on identity). For example, to access a file, managed
code must have both the code access security file permission and must also be running
under a log on identity that has NTFS file access rights. The managed libraries that are
included with the .NET Framework also provide classes for role-based security. These
allow the application to work with Windows log on identities and user groups.
The garbage collector tracks and reclaims objects allocated in managed memory.
Periodically, the garbage collector performs garbage collection to reclaim memory
allocated to objects for which there are no valid references. Garbage collection
happens automatically when a request for memory cannot be satisfied using available
free memory. Alternatively, an application can force garbage collection using the
Collect method.
What are Generations in Garbage Collector? What is the importance & use of
the
generations process?
Generations in the Garbage Collector is a way of enhancing the garbage collection
performance. In .NET, all resources are allocated space (memory) from the heap. Objects
are automatically freed from the managed heap when they are no longer required by the
[Link] are 3 Generations...0,1,2.
Generation 0 - When an object is initialized, its in generation 0. These are new objects
that
have never been played around with by the GC. As and when more objects get created, the
process of Garbage Collection is invoked by the CLR.
Generation 1 - The objects that survive the garbage collection process are considered
to
be in generation 1. These are the old objects.
Generation 2 - As more new objects get created and added to the memory, the new
objects are added to generation 0, the generation 1 old objects become older, and so are
considered to be in generation 2. Generation 2 is the highest level generation in the
garbage collection process. Any further garbage collection process occuring causes the
level 1 objects promoted to level 2, and the level 2 objects stay in level 2 itself, as this
generation level is the highest level.
The newer an object, the shorter its life is. The older an object, longer its life is.
This process also helps in categorizing the memory heap as to where the de-allocation
needs to be done first and where next.
Once this part of the graph is complete, the garbage collector checks the next root and
walks the objects again. As the garbage collector walks from object to object, if it at-
tempts to add an object to the graph that it previously added, then the garbage collec-
tor can stop walking down that path. This serves two purposes. First, it helps perfor-
mance significantly since it doesn't walk through a set of objects more than once. Sec-
ond, it prevents infinite loops should you have any circular linked lists of objects.
Once all the roots have been checked, the garbage collector's graph contains the set of
all objects that are somehow reachable from the application's roots; any objects that
are not in the graph are not accessible by the application, and are therefore considered
garbage. The garbage collector now walks through the heap linearly, looking for con-
tiguous blocks of garbage objects (now considered free space). The garbage collector
then shifts the non-garbage objects down in memory (using the standard memcpy
function that you've known for years), removing all of the gaps in the heap. Of course,
moving the objects in memory invalidates all pointers to the objects. So the garbage
collector must modify the application's roots so that the pointers point to the objects'
new locations. In addition, if any object contains a pointer to another object, the
garbage collector is responsible for correcting these pointers as well. Figure 3 shows
the managed heap after a collection.
After all the garbage has been identified, all the non-garbage has been compacted, and
all the non-garbage pointers have been fixed-up, the NextObjPtr is positioned just after
the last non-garbage object. At this point, the new operation is tried again and the re-
source requested by the application is successfully created.
Finalization is a mechanism offered by the CLR that allows an object to perform some
graceful
cleanup prior to the garbage collector reclaiming the object's memory. Finalization is
another feature of garbage collector.
Any type that wraps a native resource, such as a file, network connection, socket, mu-
tex, or other type, must support finalization. Basically, the type implements a method
named Finalize. When the garbage collector determines that an object is garbage, it
calls the object's Finalize method (if it
exists). I think of it this way: any type that implements the Finalize method is in effect
stating
that all of its objects want a last meal before they are killed.
Here is an oversimplification of what happens: when the garbage collector detects that
an object is garbage, the garbage collector calls the object's Finalize method (if it ex-
ists) and then the object's memory is reclaimed. For example, let's say you have the
following type (in C#):
Why should you avoid using a Finalize method when designing a type?
When designing a type, it's best if you avoid using a Finalize method for several rea-
sons all
related to performance:
Finalizable objects get promoted to older generations, which increases memory
pressure and prevents the object's memory from being collected when the
garbage collector determines the object is garbage. In addition, all objects
referred to directly or indirectly by this object get promoted as well.
Generations and promotions will be discussed in Part 2 of this article.
Finalizable objects take longer to allocate.
Forcing the garbage collector to execute a Finalize method can significantly hurt
performance. Remember, each object is finalized. So if I have an array of
10,000 objects, each object must have its Finalize method called.
Finalizable objects may refer to other (non-finalizable) objects, prolonging their
lifetime unnecessarily. In fact, you might want to consider breaking a type into
two different types: a lightweight type with a Finalize method that doesn't refer
to any other objects, and a separate type without a Finalize method that does
refer to other objects.
You have no control over when the Finalize method will execute. The object
may hold on to resources until the next time the garbage collector runs.
When an application terminates, some objects are still reachable and will not
have their Finalize method called. This can happen if background threads are
using the objects or if objects are created during application shutdown or
AppDomain unloading. In addition, by default, Finalize methods are not called
for unreachable objects when an application exits so that the application may
terminate quickly. Of course, all operating system resources will be reclaimed,
but any objects in the managed heap are not able to clean up gracefully. You
can change this default behavior by calling the [Link] type's
RequestFinalizeOnShutdown method. However, you should use this method with
care since calling it means that your type is controlling a policy for the entire
application.
The runtime doesn't make any guarantees as to the order in which Finalize
methods are called. For example, let's say there is an object that contains a
pointer to an inner object. The garbage collector has detected that both objects
are garbage. Furthermore, say that the inner object's Finalize method gets
called first. Now, the outer object's Finalize method is allowed to access the
inner object and call methods on it, but the inner object has been finalized and
the results may be unpredictable. For this reason, it is strongly recommended
that Finalize methods not access any inner, member objects.
Explain how two GCs are required to reclaim memory used by objects that
require finalization.
On the surface, finalization seems pretty straightforward: you create an object and
when the object is collected, the object's Finalize method is called. But there is more to
finalization than this.
When an application creates a new object, the new operator allocates the memory
from the heap. If the object's type contains a Finalize method, then a pointer to the
object is placed on the finalization queue. The finalization queue is an internal data
structure controlled by the garbage collector. Each entry in the queue points to an
object that should have its Finalize method called before the object's memory can be
reclaimed.
Figure 5 shows a heap containing several objects. Some of these objects are
reachable from the application's roots, and some are not. When objects C, E, F, I, and J
were created, the system detected that these objects had Finalize methods and
pointers to these objects were added to the finalization queue.
There is a special runtime thread dedicated to calling Finalize methods. When the
freachable queue is empty (which is usually the case), this thread sleeps. But when
entries appear, this thread wakes, removes each entry from the queue, and calls each
object's Finalize method. Because of this, you should not execute any code in a Finalize
method that makes any assumption about the thread that's executing the code. For
example, avoid accessing thread local storage in the Finalize method.
The interaction of the finalization queue and the freachable queue is quite fascinating.
First, let me tell you how the freachable queue got its name. The f is obvious and
stands for finalization; every entry in the freachable queue should have its Finalize
method called. The "reachable" part of the name means that the objects are reachable.
To put it another way, the freachable queue is considered to be a root just like global
and static variables are roots. Therefore, if an object is on the freachable queue, then
the object is reachable and is not garbage.
In short, when an object is not reachable, the garbage collector considers the object
garbage. Then, when the garbage collector moves an object's entry from the
finalization queue to the freachable queue, the object is no longer considered garbage
and its memory is not reclaimed. At this point, the garbage collector has finished
identifying garbage. Some of the objects identified as garbage have been reclassified
as not garbage. The garbage collector compacts the reclaimable memory and the
special runtime thread empties the freachable queue, executing each object's Finalize
method.
The next time the garbage collector is invoked, it sees that the finalized objects are
truly garbage, since the application's roots don't point to it and the freachable queue
no longer points to it. Now the memory for the object is simply reclaimed. The
important thing to understand here is that two GCs are required to reclaim memory
used by objects that require finalization. In reality, more than two collections may be
necessary since the objects could get promoted to an older generation. Figure 7
shows what the managed heap looks like after the second GC.
Implementing Dispose pattern can overcome all of the above pitfalls of finalization
technique offered by GC. Dispose pattern allows deterministic finalization by calling
Dispose method explicitly.
Note that a type implementing Dispose pattern should also implement finalizer so as to
ensure clean up of unmanaged resources in case user of the type forgets to call
Dispose method.
How does the generational garbage collector in the .NET CLR manage object
lifetime?
Non-deterministic finalization implies that the destructor (if any) of an object will not necessarily be
run (nor its memory cleaned up, but that's a relatively minor issue) immediately upon its going out
of scope. Instead, it will wait until first the garbage collector gets around to finding it, and then the
finalisation queue empties down to it; and if the process ends before this happens, it may not be
finalised at all. (Although the operating system will usually clean up any process-external resources
left open - note the usually there, especially as the exceptions tend to hurt a lot.)
Explain the Dispose pattern and how and when it should be used?
When creating .NET Disposable types, you usually want to create a Finalize (C# destructor
syntax), Dispose(), Dispose(bool), and inherit from [Link]. Almost all
of your actual object cleanup will occur inside Dispose(bool). That's the pattern they
came up with, and it's a good way to keep all your cleanup in one place. We'll get to cases
in a second, but first, here's a hunk of C# code plaigarized from the whitepaper:
When Disposing, the first call is always to Dispose(). Biggest take-away from one of my talks
with Brandon. All disposing starts with that call. The CLR way of doing "chaining" destructors is
the manual Dispose(bool) pattern. Basically, the user calls Dispose(), and inside that
function, Dispose(true) is called. This does a callvirt on Dispose(bool), which will thunk
down to the lowest child instance. Then, you have the manual [Link](disposing) calls
that will walk up the chain. I had to step up to my whiteboard for a while to prove to myself that this
pattern works - but it does.
This pattern should be used for freeing unmanaged resources. In a nutshell, the Garbage Collector
really only gets invoked when there's memory pressure. But the GC can't "feel" pressure from
unmanaged resources. If you have a bunch of objects hanging around that have gobs of natively
allocated memory (C++ new, or [Link]), the GC won't know about this memory
pressure, and won't begin freeing up these objects.
Why [Link]() be called inside the Dispose method?
To ensure that the Garbage Collector won't Finalize an object that's already been Disposed. In
general, you're either going to Dispose an object, or the GC will Finalize it, not both.
What is the role of the finalizer in the Dispose pattern?
The Finalizer is a backup system in this paradigm. It should be there only to ensure that all
unmanaged resources get cleaned up in case the user forgot to call Dispose() on the object. That
is, if a Disposable object is being Finalized, it's probably a mistake. So a call to Finalize() yields a
call to Dispose(false), which takes care of only those unmanaged resources it holds, those that the
GC is unable to clean up.
Note: a call to Dispose(false) should only clean up the unmanaged resources.
What is the difference between Finalize() and Dispose()?
Both Finalize and Dispose are used to free unmanaged resources. Below are the
differences.
Finalize Dispose
1. Is a destructor, called by Garbage Collector when 1. Is a method, called explicitly by the user of an
the object goes out of scope object that implements [Link] interface
2. Finalize() is implicitly called by the runtime – CLR 2. Dispose() is explicitly called by the user of the
when ever it assumes to be appropriate. object
Finalize/Destructor cannot be called by User code
3. Implement it when you have unmanaged resources 3. Same purpose as finalize, to free unmanaged
in your code, and want to make sure that these resources. However, implement this when you are
resources are freed when the Garbage collection writing a custom class that will be used by other
happens. users.
4. Finalization is not deterministic. 4. Invoking Dispose() method can
deterministically finalize any object that
implements the IDisposable interface.
// code implementation
At the end of this scope, the SqlConnection’s Dispose() method is automatically in-
voked and all resources held by this object are released.
// code implementation
class Test
{
// Some Code
~Test
{
//Necessary cleanup code
}
}
In the preceding code, the ~Test syntax declares an explicit destructor in C#, letting you write explicit cleanup
code that will run during the finalize operation.
The framework implicitly translates the explicit destructor to create a call to Finalize:
}
}
Note that the generated code above calls the [Link] method.
Can I avoid using the garbage collected heap?
All languages that target the runtime allow you to allocate class objects from the
garbage-collected heap. This brings benefits in terms of fast allocation, and avoids the
need for programmers to work out when they should explicitly 'free' each object.
The CLR also provides what are called ValueTypes—these are like classes, except that
ValueType objects are allocated on the runtime stack (rather than the heap), and
therefore reclaimed automatically when your code exits the procedure in which they
are defined. This is how "structs" in C# operate.
Managed Extensions to C++ lets you choose where class objects are allocated. If
declared as managed Classes, with the __gc keyword, then they are allocated from the
garbage-collected heap. If they don't include the __gc keyword, they behave like
regular C++ objects, allocated from the C++ heap, and freed explicitly with the "free"
method.
Is it true that objects don't always get destroyed immediately when the last
reference
goes away?
Yes. The garbage collector offers no guarantees about the time when an object will be
destroyed and its memory reclaimed.
There was an interesting thread on the DOTNET list, started by Chris Sells, about the
implications of non-deterministic destruction of objects in C#. In October 2000,
Microsoft's Brian Harry posted a lengthy analysis of the problem. Chris Sells' response
to Brian's posting is here.
Why doesn't the .NET runtime offer deterministic destruction?
Because of the garbage collection algorithm. The .NET garbage collector works by
periodically running through a list of all the objects that are currently being referenced
by an application. All the objects that it doesn't find during this search are ready to be
destroyed and the memory reclaimed. The implication of this algorithm is that the
runtime doesn't get notified immediately when the final reference on an object goes
away - it only finds out during the next 'sweep' of the heap.
Futhermore, this type of algorithm works best by performing the garbage collection
sweep as rarely as possible. Normally heap exhaustion is the trigger for a collection
sweep.
It's certainly an issue that affects component design. If you have objects that maintain
expensive or scarce resources (e.g. database locks), you need to provide some way to
tell the object to release the resource when it is done. Microsoft recommend that you
provide a method called Dispose() for this purpose. However, this causes problems for
distributed objects - in a distributed system who calls the Dispose() method? Some
form of reference-counting or ownership-management mechanism is needed to handle
distributed objects - unfortunately the runtime offers no help with this.
This issue is a little more complex than it first appears. There are really two categories
of class that require deterministic destruction - the first category manipulate
unmanaged types directly, whereas the second category manipulate managed types
that require deterministic destruction. An example of the first category is a class with
an IntPtr member representing an OS file handle. An example of the second category is
a class with a [Link] member.
For the first category, it makes sense to implement IDisposable and override Finalize.
This allows the object user to 'do the right thing' by calling Dispose, but also provides a
fallback of freeing the unmanaged resource in the Finalizer, should the calling code fail
in its duty. However this logic does not apply to the second category of class, with only
managed resources. In this case implementing Finalize is pointless, as managed
member objects cannot be accessed in the Finalizer. This is because there is no
guarantee about the ordering of Finalizer execution. So only the Dispose method
should be implemented. (If you think about it, it doesn't really make sense to call
Dispose on member objects from a Finalizer anyway, as the member object's Finalizer
will do the required cleanup.)
For classes that need to implement IDisposable and override Finalize, see Microsoft's
documented pattern.
Note that some developers argue that implementing a Finalizer is always a bad idea,
as it hides a bug in your code (i.e. the lack of a Dispose call). A less radical approach is
to implement Finalize but include a [Link] at the start, thus signalling the
problem in developer builds but allowing the cleanup to occur in release builds.
A little. For example the [Link] class exposes a Collect method, which forces the
garbage collector to collect all unreferenced objects immediately.
Also there is a gcConcurrent setting that can be specified via the application
configuration file. This specifies whether or not the garbage collector performs some of
its collection activities on a separate thread. The setting only applies on multi-
processor machines, and defaults to true.
Lots of interesting statistics are exported from the .NET runtime via the '.NET CLR xxx'
performance counters. Use Performance Monitor to view them.
The lapsed listener problem is one of the primary causes of leaks in .NET applications.
It occurs when a subscriber (or 'listener') signs up for a publisher's event, but fails to
unsubscribe. The failure to unsubscribe means that the publisher maintains a reference
to the subscriber as long as the publisher is alive. For some publishers, this may be the
duration of the application.
This situation causes two problems. The obvious problem is the leakage of the
subscriber object. The other problem is the performance degredation due to the
publisher sending redundant notifications to 'zombie' subscribers.
There are at least a couple of solutions to the problem. The simplest is to make sure
the subscriber is unsubscribed from the publisher, typically by adding an Unsubscribe()
method to the subscriber. Another solution, documented here by Shawn Van Ness, is to
change the publisher to use weak references in its subscriber list.
It's very unintuitive, but the runtime can decide that an object is garbage much sooner
than you expect. More specifically, an object can become garbage while a method is
executing on the object, which is contrary to most developers' expectations. Chris
Brumme explains the issue on his blog. I've taken Chris's code and expanded it into a
full app that you can play with if you want to prove to yourself that this is a real
problem:
using System;
using [Link];
class Win32
{
[DllImport("[Link]")]
public static extern IntPtr CreateEvent( IntPtr lpEventAttributes,
bool bManualReset,bool bInitialState, string lpName);
[DllImport("[Link]", SetLastError=true)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("[Link]")]
public static extern bool SetEvent(IntPtr hEvent);
}
class EventUser
{
public EventUser()
{
hEvent = [Link]( [Link], false, false, null );
}
~EventUser()
{
[Link]( hEvent );
[Link]("EventUser finalized");
}
IntPtr hEvent;
}
class App
{
static void Main(string[] args)
{
EventUser eventUser = new EventUser();
[Link]();
}
}
If you run this code, it'll probably work fine, and you'll get the following output:
SetEvent succeeded
EventDemo finalized
(Note that you need to use a release build to reproduce this problem.)
So what's happening here? Well, at the point where UseEvent() calls
UseEventInStatic(), a copy is taken of the hEvent field, and there are no further
references to the EventUser object anywhere in the code. So as far as the runtime is
concerned, the EventUser object is garbage and can be collected. Normally of course
the collection won't happen immediately, so you'll get away with it, but sooner or later
a collection will occur at the wrong time, and your app will fail.
A solution to this problem is to add a call to [Link](this) to the end of the
UseEvent method, as Chris explains.
During a collection, the garbage collector will not free an object if it finds one or more
references to the object in managed code. However, the garbage collector does not
recognize references to an object from unmanaged code, and might free objects that
are being used exclusively in unmanaged code unless explicitly prevented from doing
so. The KeepAlive method provides a mechanism that prevents the garbage collector
from collecting objects that are still in use in unmanaged code.
finalizers are called for objects that reference each other but are otherwise available
for garbage collection.
What are generations and how are they used by the garbage collector?
Generations are the division of objects on the managed heap used by the garbage
collector. This mechanism allows the garbage collector to perform highly optimized
garbage collection. The unreachable objects are placed in generation 0, the reachable
objects are placed in generation 1, and the objects that survive the collection process
are promoted to higher generations.
For example:
using System;
namespace GCCollectIntExample
{
class MyGCCollectClass
{
private const long maxGarbage = 1000;
[Link]();
void MakeSomeGarbage()
{
Version vt;
{
...
}
A memory leak is a particular type of unintentional memory consumption by a computer program where the
program fails to release memory when no longer needed. This condition is normally the result of a bug in a
program that prevents it from freeing up memory that it no longer needs.
Why languages that provide automatic memory management, like Java, C# are not immune to
memory leaks?
The garbage collector recovers only memory that has become unreachable. It does not free memory that is
still reachable. In .NET, this means that objects reachable by at least one reference won't be released by the
garbage collector.
You won't likely see your computer run out of memory. "Out of memory" messages are quite rare. This is be-
cause when operating systems run out of RAM, they use hard disk space to extend the memory workspace
(this is called virtual memory).
What you're more likely to see happen are "out of handles" exceptions in your Windows graphical applica-
tions. The exact exception is either a [Link].Win32Exception or a [Link]-
ryException with the following message: "Error creating window handle". This happens when two many re-
sources are consumed at the same time, most likely because of objects not being released while they should.
Another thing you may see even more often is your application or the whole computer getting slower and
slower. This can happen because your machine is simply getting out of resources.
Let me make a blunt assertion: most applications leaks. Most of the time it's not a problem because the is-
sues resulting from leaks show up only if you use applications intensively and for a long period of time.
If you suspect that objects are lingering in memory while they should have been released, the first thing you
need to do is to find what these objects are.
Look for unexpected and lingering high level objects or root containers with your favorite memory profiler. In
project X, this can be objects such as LayoutView instances (we use the MVP pattern with CAB/SCSF). In your
case, it all depends on what the root objects are.
The next step is to find why these objects are being kept in memory while they shouldn't be. This is where
debuggers and profilers really help. They can show you how objects are linked together.
Your goal should be to find the root reference. Don't stop at the first object you'll find, but ask yourself why
this object is kept in memory.
These are:
Static references
The culprits that are just listed concern your applications, but you should understand that leaks can happen
in other pieces of .NET code that your applications rely on. There can actually be bugs in libraries you use.
Let's take an example. In project X, a third-party visual controls suite is used to build the GUI. One of these
controls is used to display toolbars. The way it is used is via a component that manages a list of toolbars.
This works fine, except that even though the toolbar class implements IDisposable, the manager class never
calls the Dispose method on the toolbars it manages. This is a bug. Fortunately, a workaround is easy to find:
just call Dispose by ourselves on each toolbar. Unfortunately, this is not enough because the toolbar class it-
self is buggy: it does not dispose the controls (buttons, labels, etc.) it contains. Again, the solution is to dis-
pose each control the toolbar contain, but that's not so easy this time because each sub-control is different.
Anyway, this is just a specific example. Any libraries and components you use may cause leaks in your appli-
cations.
Static references
If an object is referenced by a static field, then it will never be released. This is also true with such things as
singletons. Singletons are often static objects, and if it's not the case, they are usually long-lived objects
anyway.
This may be obvious, but keep in mind that not only direct references are dangerous. The real danger comes
from indirect references. In fact, you must pay attention to the chains of references. What counts is the root
of each chain. If the root is static, then all the objects down the chain will stay alive forever.
If Object1 on the above diagram is static, and most likely long-lived, then all the other objects down the
reference chain will be kept in memory for a long time. The danger is that the chain can be too long to
realize that the root of the chain is static. If you care about only one level of depth, you will consider that
Object3 and Object4 will go away when Object2 goes away. That's correct, for sure, but you need to take into
account the fact that they may never go away because Object1 keeps the whole object graph alive.
Be very careful with all kinds of statics. Avoid them if possible. If not, pay careful attention to the objects
your static objects and singletons keep in memory.
A specific kind of risky statics are static events. I'll cover them just after I cover events in general.
A child form is subscribing to an event of the main form to get notified when the opacity changes.
[Link] += mainForm_OpacityChanged;
The problem is that the subscription to the OpacityChanged event creates a reference from the main form to
the child form.
See this post of mine to learn more about events and references. Here is a figure from this post that shows
the "back" reference from a subject to its observers:
MainForm keeps a reference to EventForm. This means that all the child forms that you'll open will stay in
memory while the application is alive, even if you don't use them anymore.
The simplest solution is to remove the reference by having the child forms unsubscribe from the main form's
event when they get disposed:
[Link] -= mainForm_OpacityChanged; };
Nota Bene: We have a problem here because the MainForm object remains alive until the application is shut
down. Interconnected objects with shorter lifetimes may not cause issues with memory. Any isolated graph
of objects gets unloaded automatically from memory by the garbage collector. An isolated graph of objects is
formed by two objects that only reference one another, or by a group of connected objects without any
external reference.
Another solution would be to use weak delegates, which are based on weak references. I touch this subject in
my post about events and references. Several articles on the Web demonstrate how to put this into action.
Here is a good one, for example. Most of the solutions you'll find are based on the WeakReference class.
Note that a solution for this exists in WPF, in the form of the WeakEvent pattern.
Event handlers with missing unsubscriptions from events on static or long-lived objects are a problem.
Another one is static events.
Static events
[Link] += SystemEvents_UserPreferenceChanged;
This is similar to the previous case, except that this time we subscribe to a static event. Since the event is
static, the listener form object will never get released.
[Link] -= SystemEvents_UserPreferenceChanged;
You've paid attention to events, static or not? Great, but that's not enough. You can still get lingering
references even with correct cleanup code. This happens sometimes simply because this cleanup code
doesn't get invoked...
Using the Dispose method or the Disposed event to unsubscribe from event and to release resources is a
best practice, but it's useless if Dispose doesn't get called.
Let's take an interesting example. Here is sample code that creates a context-menu for a form.
After the form has been closed and disposed, the ContextMenuStrip is still alive in memory! Note: To see the
problem happen, show the context-menu with a right-click before closing the form.
Again this is a problem with static events. The solution is the same as usual:
[Link]();
I guess you start to understand how events can be dangerous in .NET if you don't pay careful attention to
them and the references they imply.
What I want to stress here is that it's easy to introduce a leak with just a line of code. Would you have
thought about potential memory leaks when creating a context-menu?
It's even worst than what you imagine. Not only the ContextMenuStrip is maintained alive, but it maintains
the complete form alive with it! The ContextMenuStrip references the form. The result is that the form will be
alive as long as the ContextMenuStrip is. Oh, of course you should not forget that while the form is alive, it
maintains itself a whole set of objects alive - the controls and components it contains, to start with.
This is something that I find important enough to warrant a big warning. A small object can potentially
maintain big graphs of other objects in memory. I've seen this happen all the time in project X. This is the
same with water: a small leak can cause big damages.
Because a single control points to its parent or to events of its parent, it has the potential to keep a whole
chain of container controls alive if it hasn't been disposed. And of course, all the other controls contained in
these containers are also kept in memory. This can for example lead to a complete form and all its content
that remain in memory for ever (at least until the application stops).
At this point, you may be wondering if this problem always exists with ContextMenuStrip. It doens't. most of
the time, you create ContextMenuStrips with the designer directly on their form, and in this case Visual
It's great to have your classes implement the IDisposable interface and to include calls to Dispose and using
blocks all over your code, but that's really useful only if the Dispose methods are implemented correctly.
This remark may seem a bit stupid, but if I make it it's because I've seen many cases where the code of
Dispose methods was not complete.
You know how it happens. You create your classes; you have them implement IDisposable; you unsubscribe
from events and release resources in Dispose; and you call Dispose everywhere. That's fine, until later on
you have one of your classes subscribe to a new event or consume a new resource. It's easy to code, you're
eager to finish coding and to test your code. It runs fine and you're happy with it. You checkin. Great! But...
oops, you've forgotten to update Dispose to release everything. It happens all the time.
******************************************************************
Threading
What is Multi-tasking?
It’s a feature of modern operating systems with which we can run multiple programs at
same time. Example Word, Excel, etc.
What is Multi-threading?
Multi-threading forms subset of Multi-tasking instead of having to switch between
programs this feature switches between different parts of the same program. Example
you are writing in word and at the same time word is doing a spell check in
background.
What is a thread?
A thread is an independent execution path, able to run simultaneously with other threads. A thread
is the basic unit to which the operating system allocates processor time.
A C# program starts in a single thread created automatically by the CLR and operating system
(the "main" thread), and is made multi-threaded by creating additional threads.
The CLR assigns each thread its own memory stack so that local variables are kept separate. In the
next example, we define a method with a local variable, then call the method simultaneously on the
main thread and a newly created thread:
??????????
A separate copy of the cycles variable is created on each thread's memory stack, and so the output
is, predictably, ten question marks.
Process Thread
A context switch is the computing process of storing and restoring the state
(context) of a CPU so that execution can be resumed from the same point at a later
time. This enables multiple processes to share a single CPU resource. The context
switch is an essential feature of a multitasking operating system. Context
switches are usually computationally intensive and much of the design of operating
systems is to optimize the use of context switches. A context switch can mean a
register context switch, a task context switch, a thread context switch, or a process
context switch.
What are the different ways through which threads can share data? Is it a problem if
data is shared between threads? If yes, how can it be solved?
Threads share data if they have a common reference to the same object instance. Here's an ex-
ample:
class ThreadTest {
bool done;
static void Main() {
ThreadTest tt = new ThreadTest(); // Create a common instance
new Thread ([Link]).Start();
[Link]();
}
// Note that Go is now an instance method
void Go() {
if (!done) { done = true; [Link] ("Done"); }
}
}
Because both threads call Go() on the same ThreadTest instance, they share the done field. This
results in "Done" being printed once instead of twice:
Done
Static fields offer another way to share data between threads. Here's the same example with
done as a static field:
class ThreadTest {
static bool done; // Static fields are shared between all threads
static void Main() {
new Thread (Go).Start();
Go();
}
static void Go() {
if (!done) { done = true; [Link] ("Done"); }
}
}
Both of these examples illustrate another key concept – that of thread safety (or, rather, lack of it!)
The output is actually indeterminate: it's possible (although unlikely) that "Done" could be printed
twice. If, however, we swap the order of statements in the Go method, then the odds of "Done" be-
ing printed twice go up dramatically:
The problem is that one thread can be evaluating the if statement right as the other thread is execut-
ing the WriteLine statement – before it's had a chance to set done to true.
What is multithreading?
Multithreading is a technique that can be used to perform time consuming tasks in a separate
additional thread other than the main application thread.
When you, for example, have a time-consuming function, you may need to call this function as a
response of a button click. Now, instead of freezing all your application waiting for this function to
return / to finish, you can create a new thread and assign this function to. When you do this, your
application interface will not be blocked and you can use it to perform other tasks. At the same
time, your time-consuming task is being carried out in the background.
You can think of it as the two threads: the main one, and the newly created one. Both are running
in parallel, and this improves the performance and responsiveness of your application.
Notes:
Each time a thread is created, a certain amount of memory is consumed to hold this thread
context information. Hence, the number of threads that can be created is limited by the
amount of available memory.
More threads does not mean a faster responsive application, instead it can decrease the
performance of your application.
How having worker threads as background threads can be beneficial? What is the problem of
having worker threads as foreground threads?
This becomes relevant only when multiple threads are simultaneously active.
What is the output of below program? Or what happens when an exception is thrown
in a different thread?
using System;
using [Link];
namespace ConsoleApplication1
{
class Program
{
public static void Main()
{
try
{
new Thread(Go).Start();
}
catch (Exception ex)
{
// We'll never get here!
[Link]("Exception!");
}
}
The try/catch statement here is effectively useless, and the newly created thread will be
encumbered with an unhandled NullReferenceException. This behavior makes sense when you
consider a thread has an independent execution path.
One can cut the work by using a wrapper or helper class to perform the job, such as BackgroundWorker.
Why a try/catch block is required in every thread entry method – at least in production ap-
plications?
An unhandled exception on any thread shuts down the whole application, meaning ignoring the ex-
ception is generally not an option. Hence a try/catch block is required in every thread entry method
– at least in production applications – in order to avoid unwanted application shutdown in case of
an unhandled exception. This can be somewhat cumbersome – particularly for Windows Forms
programmers, who commonly use the "global" exception handler, as follows:
What is a blocked thread? What is the new state after a thread is blocked?
When a thread waits or pauses as a result of using the constructs like sleep and join, it's said to
be blocked.
Once blocked, a thread immediately relinquishes its allocation of CPU time, adds
WaitSleepJoin to its ThreadState property, and doesn’t get re-scheduled until unblocked.
Why lock must not be obtained on a public type or instances beyond your code's
control? Or why lock should be avoided on constructs such as lock (this), lock (typeof
(MyType)), and lock ("myLock")?
lock (this) is a problem if the instance can be accessed publicly.
lock (typeof (MyType)) is a problem if MyType is publicly accessible.
lock(“myLock”) is a problem because any other code in the process using the same string, will
share the same lock.
Best practice is to define a private object to lock on, or a private static object variable to protect data
common to all instances.
lock(this) can be problematic if the instance can be accessed publicly, because code beyond your
control may lock on the object as well. This could create deadlock situations where two or more threads wait
for the release of the same object. Locking on a public data type, as opposed to an object, can cause
problems for the same reason. It breaks encapsulation and can lead to deadlocks. Locking on literal strings is
especially risky because literal strings are interned by the common language runtime (CLR). This means that
there is one instance of any given string literal for the entire program, the exact same object represents the
literal in all running application domains, on all threads. As a result, a lock placed on a string with the same
contents anywhere in the application process locks all instances of that string in the application. As a result,
it is best to lock a private or protected member that is not interned. Some classes provide members
specifically for locking. The Array type, for example, provides SyncRoot. Many collection types provide a
SyncRoot member as well.
lock (x)
{
DoSomething();
}
Generally you only use a Mutex across processes, e.g. if you have a resource that multiple
applications must share, or if you want to build a single-instanced app (i.e. only allow 1 copy to be
running at one time).
A semaphore allows you to limit access to a specific number of simultaneous threads, so that you
could have, for example, a maximum of two threads executing a specific code path at a time.
There are two functionally similar versions of this class: Semaphore and
SemaphoreSlim. The latter was introduced in Framework 4.0 and has been
optimized to meet the low-latency demands of parallel programming. It’s also
useful in traditional multithreading because it lets you specify a cancellation
token when waiting. It cannot, however, be used for interprocess signaling.
1 wants to enter
1 is in!
2 wants to enter
2 is in!
3 wants to enter
3 is in!
4 wants to enter
5 wants to enter
1 is leaving
4 is in!
2 is leaving
5 is in!
If the Sleep statement was instead performing intensive disk I/O, the
Semaphorewould improve overall performance by limiting excessive concurrent
hard-drive activity.
There are two kinds of synchronization events: AutoResetEvent, and ManualResetEvent. Both are derived
from EventWaitHandle class.
Example
class BasicWaitHandle
{
static EventWaitHandle wh = new AutoResetEvent (false);
static void Main() {
new Thread (Waiter).Start();
[Link] (1000); // Wait for some time...
[Link](); // OK - wake it up
}
static void Waiter() {
[Link] ("Waiting...");
[Link](); // Wait for notification
[Link] ("Notified");
}
}
****************************
What is Apartment threading? Why do we need in .NET?
Apartment threading is an automatic thread-safety regime, closely allied to COM – Microsoft's
legacy Component Object Model. While .NET largely breaks free of legacy threading models, there
are times when it still crops up because of the need to interoperate with older APIs. Apartment
threading is most relevant to Windows Forms, because much of Windows Forms uses or wraps the
long-standing Win32 API – complete with its apartment heritage.
What is an apartment? What is the default apartment for a thread created in .NET? How to
assign explicitly a .NET thread to an apartment?
An apartment is a logical "container" for threads. Apartments come in two sizes – "single" and
"multi". A single-threaded apartment contains just one thread; multi-threaded apartments can con-
tain any number of threads. The single-threaded model is the more common and interoperable of
the two.
One can also request that the main thread join a single-threaded apartment using the STAThread
attribute on the main method:
class Program {
[STAThread]
static void Main() {
...
Why a Windows Forms program should have the [STAThread] attribute on its main method?
The types in the [Link] namespace extensively call Win32 code designed to work
in a single-threaded apartment. For this reason, a Windows Forms program should have the
[STAThread] attribute on its main method, otherwise one of two things will occur upon reaching
Win32 UI code:
it will marshal over to a single-threaded apartment
it will crash
Can we call a method or property on a control from any thread other than the one that cre-
ated it in a multi-threaded application? If no, what are the solutions to manage worker
threads in Windows Forms and WPF applications?
No. In a multi-threaded Windows Forms application, it's illegal to call a method or property on a
control from any thread other than the one that created it. There are two solutions using:
using System;
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[Link]();
}
if ([Link] == true)
[Link]((MethodInvoker)delegate()
{
UpdateLabel(text);
});
else
[Link] = text;
}
}
}
If we remove STAThread attribute from Main method, whether application would run?
No
How do you find the sum of numbers from 1 to 1 million - use a thread or without use of
thread? Justify which you would choose.
You've a grid and 10 million records to show. The data comes from a background thread and
you need to update the grid. The update of grid happens in UI thread. This is a performance
bottleneck and makes the update of data slow. How to improve the performance in updating
of grid?
Or can we create multiple UI threads in an Windows Forms or WPF application?
[Link]
threads/
Introduction
It’s a good, time-proven practice to perform long, CPU intensive tasks on some sort of a
background thread to improve your UI thread responsiveness. Sometimes though UI-related
tasks themselves can be quite expensive. WPF, for examples, forces you to do all UI work
on the thread that created the UI. A very flexible WPF measure/layout paradigm for UI
rendering also comes with high CPU usage cost. In a very UI intensive application (for
example, trading app with about ten windows showing real-time montage and blotter data)
simply the cost of generating and laying out visuals can become too high for a single thread
to keep up. When your UI thread saturates individual windows may start skip rendering
cycles, become slow to response to user input, or even freeze. If your UI thread approaches
this kind of saturation you should consider creating dedicated UI threads for some (or all) of
your UI-intensive windows. This post is a step by step walk-through of doing just that.
To start lets create a basic WPF application we can work with. In Visual Studio go
File/New/Project, then Visual C#, Windows, WPF Application. Name the project
“WpfThreadLab” and click “OK”. The automatically generated [Link] window
doesn’t display anything by default, so let add something useful for out lab. We will display
the ID for the thread that owns the window. First open [Link] and add the
following code”:
using [Link];
using [Link];
namespace WpfThreadLab
{
/// <summary>
/// Interaction logic for [Link]
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
Constructor creates data context containing thread’s ID that we can data bind to. We also
add a click event handler that we will use to create new windows on demand. This is how
corresponding [Link] may look like:
<Window
x:Class="WpfThreadLab.Window1"
xmlns="[Link]
xmlns:x="[Link]
Title="Window1" Height="100" Width="200"
>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Thread's ID is "/>
<TextBlock Text="{Binding ThreadId}"/>
</StackPanel>
<Button
Click="OnCreateNewWindow"
Content="Create new Window1"
/>
</StackPanel>
</Window>
If you run the application now you should see the following window:
Clicking on the button will create new clones of the window. You will see that they all
belong to default UI thread with managed ID 1.
The quick and dirty solution may include the following modifications to our
OnCreateNewWindow handler:
[Link]([Link]);
[Link]();
}
The window creation code is exactly the same, except that we wrapped it in a thread
delegate. This delegate is passed to a newly created thread that is started at the end of the
handler. Note that we explicitly setting new thread’s apartment state to STA, this is a WPF
requirement.
If you run the application now and click on the button, you will notice that a new window
appears momentarily and then dies. The reason is that our newly created thread is not
enabled to support WPF window infrastructure. In particular, it provides no support for
Windows message pumping, and this is something we will fill in next.
WPF window like any other window relies on Windows message pump. In WPF word this
functionality is provided by a class called Dispatcher. WPF Application object takes care of
starting dispatcher for the main UI thread for us, but we have to explicitly start it for our
own private UI threads. The easiest way to do it is to call static method Run() on the
Dispatcher class:
{
Window1 w = new Window1();
[Link]();
[Link]();
});
[Link]([Link]);
[Link]();
}
The code in bold shows the modification. This blocks the thread and starts a message pump
on it. If you run application now and start clicking the button you will notice that fully
functional window is created every time you click, and every time on a new thread.
There is one catch to our simplified solution. Closing a particular window does NOT
terminate this window’s thread dispatcher, so the thread keeps running and, after closing
all windows, the process will not terminate and will become a ghost process. Simple (and
not correct) solution to this is to mark our threads as background (using
[Link] = true;). This will force them to terminate when main UI thread
terminates. The proper implementation will gracefully shut down the dispatcher when it is
no longer needed. The code below is an example of a strategy to terminate the dispatcher
when window closes:
[Link]();
});
[Link]([Link]);
[Link]();
}
The code above in bold accomplishes the task of shutting down the dispatcher for window’s
UI thread.
Conclusion
Running multiple UI threads in WPF application is actually rather trivial. In the nutshell it
boils down to creating your dedicated thread and creating your windows inside this thread’s
proc. Remember to conclude your UI thread with a call to WPF dispatcher. Also, decide on
your “exit” strategy (often, shutting down dispatcher in response to closing the primary
window for this thread).
Thread Pool
[Link] returns a Task object, which you can then use to monitor the task—for in-
stance, you can wait for it to complete by calling its Wait method.
Any unhandled exceptions are conveniently rethrown onto the host thread when you call a task's Wait
method.
(If you don’t call Wait and abandon the task, an unhandled exception will shut down the process as with an
ordinary thread.)
The generic Task<TResult> class is a subclass of the nongeneric Task. It lets you get a return value back
from the task after it finishes executing. In the following example, we download a web page using
Task<TResult>:
QueueUserWorkItem
To use QueueUserWorkItem, simply call this method with a delegate that you want to run on a pooled
thread:
static void Main()
{
[Link] (Go);
[Link] (Go, 123);
[Link]();
}
static void Go (object data) // data will be null with the first call.
{
[Link] ("Hello from the thread pool! " + data);
}
// Output:
Hello from the thread pool!
Hello from the thread pool! 123
Our target method, Go, must accept a single object argument (to satisfy the WaitCallback delegate).
This provides a convenient way of passing data to the method, just like with ParameterizedThread-
Start. Unlike with Task, QueueUserWorkItem doesn't return an object to help you subsequently man-
age execution. Also, you must explicitly deal with exceptions in the target code—unhandled exceptions will
take down the program.
Asynchronous delegates
[Link] doesn’t provide an easy mechanism for getting return values back
from a thread after it has finished executing. Asynchronous delegate invocations (asynchronous delegates for
short) solve this, allowing any number of typed arguments to be passed in both directions. Furthermore, un-
handled exceptions on asynchronous delegates are conveniently rethrown on the original thread (or more ac-
curately, the thread that calls EndInvoke), and so they don’t need explicit handling.
Don’t confuse asynchronous delegates with asynchronous methods (methods starting with Begin or End, such
as [Link]/[Link]). Asynchronous methods follow a similar protocol outwardly, but
they
exist to solve a much harder problem, which we describe in Chapter 23 of C# 4.0 in a Nutshell.
Here’s how you start a worker task via an asynchronous delegate:
1. Instantiate a delegate targeting the method you want to run in parallel (typically one of the predefined
Func
delegates).
2. Call BeginInvoke on the delegate, saving its IAsyncResult return value.
BeginInvoke returns immediately to the caller. You can then perform other activities while the
pooled thread is working.
3. When you need the results, call EndInvoke on the delegate, passing in the saved IAsyncResult ob-
ject.
In the following example, we use an asynchronous delegate invocation to execute concurrently with the main
thread, a simple method that returns a string’s length:
}
static int Work (string s) { return [Link]; }
static void Done (IAsyncResult cookie)
{
var target = (Func<string, int>) [Link];
int result = [Link] (cookie);
[Link] ("String length is: " + result);
}
The final argument to BeginInvoke is a user state object that populates the AsyncState property of
IAsyncResult. It can contain anything you like; in this case, we’re using it to pass the method delegate
to the completion callback, so we can call EndInvoke on it.
How do you decide whether you need a dedicated thread or a thread pool
thread?
.NET’s thread pool has some shortcomings which can affect the choice between using a
dedicated thread instead of a thread from the thread pool. It is usually said that a
dedicated thread is favorable in the following scenarios:
When a foreground thread is required: All thread pool threads are initialized as
background threads.
When it is required to have a thread with a particular priority.
When a thread is required to be aborted prematurely
When a thread must be placed in a single-threaded apartment (STA): All thread
pool threads are set in the MTA apartment by default
For long running tasks when the thread pool thread is often blocked for long
periods (This may starve other parts of the application which rely on threads
from the thread pool)
The thread pool is shared by all AppDomains in a process. Consider this if you have
more than one AppDomain in your process.
Thread considerations. Also, the specifics of how you use your threads can help you
find the best code. This next table compares the threading scenarios and which class is
best.
Generally, you should prefer ThreadPool when you need many threads. Threads aren't
always useful, such as for I/O operations, which many computers can't multithread as
well. With the era of multicore systems, we need threads and BackgroundWorker is an
excellent shortcut.
You do not have to create, manage, schedule, and terminate your thread, the thread pool
class do all of this for you.
There are no worries about creating too many threads and hence affecting system perfor-
mance. Thread pool size is constrained by the .NET runtime. The number of threads you
can use at the same time is limited.
You need to write less code, because the .NET framework manages your thread internally
with a set of well tested, and bug free routines.
Despite the ease of use, the thread pool has the following limitations or disadvantages when com-
pared to manually managing your threads:
With thread pool, you have no control over the state and priority of the thread.
With thread pool, you cannot give a stable identity to your thread and keep tracking it.
When submitting a process to the thread pool, you have no idea when the process will be
executed. Your process may be delayed when there are high demands on the thread pool.
The thread pool is not suitable when you want to run two tasks or processes using two
threads, and need these two tasks to be processed simultaneously in a deterministic fash-
ion.
The .NET framework uses the thread pool for asynchronous operations, and this places
additional demand on the limited number of available threads.
Despite of robust application isolation, there are situations where your application code
can be affected by another application code.
In situations where you cannot use the thread pool because of its limitations, you can create new
threads manually and manage them yourself. This technique is much more complex than using the
thread pool, but it gives you more control over your threads.
Example
modify data which the UI thread might be about to use for display purposes. For exam-
ple, if you have a Person with FirstName and LastName properties, and you did:
then the UI may well end up displaying "Keyser Spacey". (There's an outside chance it
could display "Kevin Soze" but only through the weirdness of the memory model.)
Unless you have this sort of issue, however, [Link] is easier to get right,
and will avoid your background thread from having to wait for no good reason. Note
that the Windows Forms team has guaranteed that you can use [Link] in
a "fire and forget" manner - i.e. without ever calling EndInvoke. This is not true of
async calls in general: normally every BeginXXX should have a corresponding EndXXX
call, usually in the callback.
Using Threads
// Asynchronous methods.
public void Method1Async(string param);
public void Method1Async(string param, object userState);
public event Method1CompletedEventHandler Method1Completed;
The fictitious AsyncExample class has two methods, both of which support synchronous and asyn-
chronous invocations. The synchronous overloads behave like any method call and execute the op-
eration on the calling thread; if the operation is time-consuming, there may be a noticeable delay
before the call returns. The asynchronous overloads will start the operation on another thread and
then return immediately, allowing the calling thread to continue while the operation executes "in
the background."
The last two features are particularly useful – it means you don't have to include a try/catch block
in your worker method, and can update Windows Forms and WPF controls without needing to call
[Link].
class Program
{
static BackgroundWorker bw = new BackgroundWorker();
static void Main()
{
[Link] += bw_DoWork;
[Link] ("Message to worker");
[Link]();
}
{
// This is called on the worker thread
[Link] ([Link]); // writes "Message to worker"
// Perform time-consuming task...
}
}
What are the different timer classes in the .NET Framework Class Library?
The .NET Framework provides four timers. Two of these are general-purpose multithreaded timers:
[Link]
[Link]
The other two are special-purpose single-threaded timers:
[Link] (Windows Forms timer)
[Link] (WPF timer)
The multithreaded timers are more powerful, accurate, and flexible; the single-threaded timers are safer and
more convenient for running simple tasks that update Windows Forms controls or WPF elements.
You can update user You can update user [Link] is This means that the
interface elements and interface elements required. code inside your
controls directly from and controls directly Elapsed event
Tick event handling from Tick event han- handler must
code, without calling dling code, without conform to a golden
[Link]. calling Dispatch- rule of Win32
[Link]. programming: an
instance of a control
should never be
accessed from any
thread other than the
thread that was used
to instantiate it. But,
it exposes a public
SynchronizingObject
property. Setting this
property to an
instance of a
Windows Form (or a
control on a
Windows Form) will
ensure that the code
in your Elapsed
event handler runs
on the same thread
on which the
SynchronizingObject
was instantiated.
The Windows timer The WPF timer is, in Timer event runs Timer event runs on
is, in effect, a sin- effect, a sin- on worker thread. UI or worker thread.
glethreaded timer. glethreaded timer. The .NET
Timer event runs on Timer event runs on Framework
UI thread. UI thread. documentation refers
to the
[Link]
r class as a server-
based timer that was
designed and
optimized for use in
multithreaded
environments.