C# Interview Question for Experienced
·
Q1. Difference b/w
convert.toint32 vs int.parse vs tryparse
ð
Int.parse
not handle null and balck value its throws exception
ð
int.tryparse
handle null and balck value and convert them zero
ð
Int.parse
and toint 32 giv out of format exception
ð
Tryparse never give exception and its best to use
ð
Int32
not handle blank value its give exception
Syntax: bool output;
output = int.TryParse(str1,out finalResult); // 9009
Q2.
IS VS AS
Is Operator is used to Check the Compatibility of an
Object with a given Type and it returns the result as a Boolean (True Or
False).
if (someObject
isStringBuilder) .
AS : As
Operator is used for Casting of Object to a given Type or a Class.
The as
operator does the same job of is
operator but the difference is instead of bool
, it returns the object if
they are compatible to that type, else it returns null
StringBuilder b =
someObject asStringBuilder;
if (b != null) ..
Q3. Access
Modifier
public
The type or member can be accessed by any other code in the same assembly or
another assembly that references it.
private
The type or member can be accessed only by code in the same class or struct.
protected
The type or member can be accessed only by code in the same class, or in a
class that is derived from that class.(Derived class may be in another assembly
also)
internal
The type or member can be accessed by any code in the same assembly, but not
from another assembly.
protected internal The type or
member can be accessed by any code in the assembly in which it is declared, or
from within a derived class in another assembly.1
private protected The type or
member can be accessed only within its declaring assembly, by code in the same
class or in a type that is derived from that class
Note : Child class
by must be less accessible or equal accessible
DataTable
Clonemethod clones the structure of the data Table,
including all data Table schemas and constraints. Not data.
DataTable.Copymethod copies both the structure and data.
*Nth Highest Salary :
--option 1
Select TOP 1 Salary as '3rd Highest Salary'
from (SELECT DISTINCT TOP 3 Salary from Employee ORDER BY
Salary DESC)
a ORDER BY Salary ASC)
--option 2
SELECTa.Name,a.sal
FROM(SELECT Name,sal,DENSE_RANK() over(ORDER BY sal) AS rk
FROM Person1) as a where rk=3
--option 3
select * from (
select e.*, row_number()
over (order by sal desc) rn from emp e
)
where rn = 2;
Self-join Manager name:
SELECT e1.Name EmployeeName,
e2.name AS ManagerName FROM Employee e1 INNER JOIN Employee e2 ON e1.ManagerID
= e2.EmployeeID
Destructor: implicitly calls the Finalize method, they are
technically same. Dispose is available with those object which implements
IDisposable interface.
The
destructor implicitly calls Finalize on the base class of the object.
Example from
the same link:
class Car
{
~Car()
// destructor
{
// cleanup statements...
}
}
Destructor
code is implicitly translated to the following code:
protected
override void Finalize()
{
try
{ //
Cleanup statements...
}
finally
{
base.Finalize();
}
}
*Answer:
1.
Difference
b/w == and Equals :
string o = "my name is sujeet";
string o1 = "my name is
sujeet";
Console.WriteLine(o== o1); //
return false
Console.WriteLine(o.Equals(o1));
// return true
·
== => compare object reference only
·
Equals
compare content only
·
For string
data always do content check only
2.
Is and As
Keyword
ð Is check variable type and return true and false
ð The is
operator in C# is used to check the
object type and it returns a bool
value: true if
the object is the same type and false if
no
ð The as
operator does the same job of is
operator but the difference is instead of bool
, it returns the object if
they are compatible to that type, else it returns null
.
ð As is used to check compatibility from one opject type to another
object str = "sujeet";
if (str isstring)
{
Console.WriteLine("is same type");
}
string x = str asstring;
3.
Int 32 vs parse int vs tryparse
=> int.Parse (string s) =>method converts the string to integer. If string s is null, then it will
throw ArgumentNullException. If string s is other than integer value, then it
will throw FormatException. If string s represents out of integer ranges, then
it will throw OverflowException.
=>Convert.ToInt32 (string s)
method
converts the string
to integer. If string s
is null
,
then it will return 0 rather than
throw ArgumentNullException. If string s
is
other than integer value, then it will throw FormatException.
If string s
represents out of integer ranges,
then it will throw OverflowException.
=>
int.TryParse(string s,out int)
method
converts the string
to integer out
variable
and returns true
if successfully parsed, otherwise false
.
If string s
is null
,
then the out
variable has 0
rather
than throw ArgumentNullException. If string s
is
other than integer value, then the out
variable
will have 0
rather than FormatException.
If string s
represents out of integer ranges,
then the out
variable will have 0
rather
than throw OverflowException.
string str1="9009";
string str2=null;
string
str3="9009.9090800";
string
str4="90909809099090909900900909090909";
int finalResult;
bool output;
output = int.TryParse(str1,out
finalResult); // 9009
output = int.TryParse(str2,out
finalResult); // 0
output = int.TryParse(str3,out
finalResult); // 0
output = int.TryParse(str4, out
finalResult); // 0
4.
Dynamic vs
var keyword :
ð Var is early bounded and its compile time .
ð Var introduced in 3.0
ð var
declarations are resolved at
compile-time.
ð Dynamic is late bounded and introduced
in 4.0
ð Dynamic internally uses reflection
ð
ð Table of difference
var
|
dynamic
|
Introduced in C# 3.0 |
Introduced in C# 4.0 |
Statically
typed – This means the type of variable declared is decided by
the compiler at compile time. |
Dynamically
typed - This means the type of variable declared is decided by
the compiler at runtime time. |
Need to
initialize at the time of declaration.
e.g., var str=”I am a string”;
Looking at the value assigned to the variable str ,
the compiler will treat the variable str as
string. |
No need to
initialize at the time of declaration.
e.g., dynamic str;
str=”I
am a string”; //Works fine and compiles
str=2; //Works
fine and compiles |
Errors
are caught at compile time.
Since the compiler knows about the type and the methods and
properties of the type at the compile time itself |
Errors
are caught at runtime
Since the compiler comes to about the type and the methods and
properties of the type at the run time. |
Visual
Studio shows intellisense since the type of
variable assigned is known to compiler. |
Intellisense
is not available since the type and its related
methods and properties can be known at run time only |
e.g., var obj1;
will throw a compile error since the
variable is not initialized. The compiler needs that this variable should be
initialized so that it can infer a type from the value. |
e.g., dynamic obj1;
will
compile; |
e.g. var obj1=1;
will compile
var
obj1=” I am a string”;
will
throw error since the compiler has already decided that the type of
obj1 is System.Int32 when the value 1 was assigned to it. Now assigning a
string value to it violates the type safety. |
e.g. dynamic obj1=1;
will compile and run
dynamic
obj1=” I am a string”;
will
compile and run since the compiler creates the
type for obj1 as System.Int32 and then recreates the type as string when the
value “I am a string” was assigned to it.
This code will work fine. |
5.
Out vs ref keyword
ð Out and ref , both are passed be reference
ð The ref keyword
is used to pass an argument as a reference.
This means that when value of that parameter is changed in the
method, it gets reflected in the calling method. An argument that
is passed using a ref keyword must be initialized in the
calling method before it is passed to the called method
ð The
out keyword is also used to pass an argument like ref keyword, but the argument
can be passed without assigning any value to it. An argument that is passed
using an out keyword must be initialized in the called method before it returns
back to calling method.
ð Both
ref and out cannot be used in method overloading simultaneously. However, ref
and out are treated differently at run-time but they are treated same at
compile time (CLR doesn't differentiates between the two while it created IL
for ref and out).
ð Properties cannot be passed to ref or out
parameters since internally they are functions and not members/variables.
ð
6.
Extension Method :
ð Help you to add new method to exiting types without modifying the
original code, inheritance, or aggregating
publicstaticclasssomemoremath
{
publicstaticint Subtract( thiswrappermath obj,int a, int b)
{
return a - b;
}
}
Main.cs
wrappermath obj = newwrappermath();
int result = obj.add(10, 100);
Console.WriteLine(result);
result = obj.Subtract(10, 100);
Console.ReadLine();
7
Constant vs static vs read only
·
Covariance vs contra variance
Solidprinciples:
·
Software design principles are a set of
guidelines that helps developers to make a good system design
Dependencyinjection:
1. Dependency Injection (DI) is a software design pattern
that allows us to develop loosely coupled code.
2. DI is a great way to reduce tight coupling between
software components.
3. DI also enables us to better manage future changes and
other complexity in our software.
4. The purpose of DI is to make code maintainable.
·
Reduces class coupling
·
Increases code
reusability
·
Improves code
maintainability
·
Improves application
testing
·
Centralized
configuration
·
Suppose your Client
class
needs to use a Service
class
component, then the best you can do is to make your Client
class
aware of an Service
interface
rather than a Service
class.
In this way, you can change the implementation of the Service
class
at any time (and for how many times you want) without breaking the host code.
Note: The process of
injecting (converting) coupled (dependent) objects into decoupled (independent)
objects is called Dependency Injection.
Types of Dependency injection
1.
Constructor injection
2.
Property injection
3.
Method injection
DI
and Service Locator are the ways of implementing IOC.
A DI Container is a framework to create dependencies and inject
them automatically when required. It automatically creates objects based on
request and injects them when required. DI Container helps us to manage
dependencies with in the application in a simple and easy way.
We can also manage an application dependencies without a DI
Container, but it will be like as POOR MAN’S DI
and we have to
do more work, to make it configured and manageable.
1.
Autofacs
2. Unity container
2.
Castle Windsor
3.
Structure map
4.
Sprint net
What happens if we apply DataMember attributes to
Static Fields?
Ans: Ignored
'
Claim based
autorization in .net
ans: 4.5
Design pattern vs Design principle Vs
Architectural Style :
Design pattern:
·
Patterns are
common solutions to object-oriented
programming problems.
They are solutions to real
world problems that pop up time and again, so instead of reinventing the wheel,
we follow the design patterns that are well-proven, tested by others, and safe
to follow. Now, design patterns are specific; there are terms and conditions
only in which a design pattern can be applied.
Examples:
·
Singleton Pattern ( One class can
only have one instance at a time )
·
Adapter Pattern ( Match interface of
different classes )
·
It provides low level solution (implementation) for the commonly
occurring object oriented problem. In another word, design pattern suggest
specific implementation for the specific object oriented programming problem.
For example, if you want create a class that can only have one object at a time
then you can use Singleton design pattern which suggests the best way to create
a class that can only have one object.
·
Design patterns are tested by others and safe to follow. E.g.
Gang of Four patterns: Abstract Factory, Factory, Singleton, Command etc
·
It is at code level or
pseudo code
·
Design Principle: Solid
·
It provides high level guide lines to design
better software applications. Design principles do not provide implementation
and not bound to any programming language.
·
Design
principles are core abstract principles which we are supposed to follow while
designing software architect.Remember they aren't concrete; rather
abstract.s
Architectural style/principles:
They are
just principlesand they are just one liner which we need to follow
And how we
follow it up us using java or c# etc
Example:
Rest,SOA,ioc
Architecture pattern:
Its block
level diagram like Model View controller or multiple layer architecture
And it up to
user how they implements these layer
Example:
MVC, MVVM, multilayer project
Difference b/w thread and
task:
A task is simply a set of instructions loaded
into the memory.
A
program is a set of executable instructions.
A
running instance of a program is called a process002E
*Tuples In C#:
Often, we want to return more than one value
from a class method. Prior to the introduction of tuples in .NET, there were
three common ways to do so.
- Out parameters
- Class or struct types
- Anonymous types returned
through a dynamic return type
Tuples solve this problem. Tuples aren’t new
to C# or .NET. Tuples were first introduced as a part of .NET Framework 4.0.
A tuple is a data structure
that provides an easy way to represent a single set of data. The System.Tuple
class provides static methods to create tuple objects.
Tuples allow us to,
- Create, access, and manipulate
a data set
- Return a data set from a method
without using out parameter
- Pass multiple values to a
method through a single parameter
Create and Access Tuples:
We can create a Tuple<> using its
constructor or the "Create" method. The code snippet in Listing 1
creates a 3-tuple using a constructor. The tuple is a set of 3 data types
including two strings and one int that represents an author's name, book title,
and year of publication
1.
// Create a 3-tuple
2.
var author = new Tuple<string, string, int>("Mahesh Chand", "ADO.NET Programming", 2003);
3.
4.
// Display author info
5.
System.Console.WriteLine("Author {0} wrote his first book titled {1} in {2}.", author.Item1, author.Item2, author.Item3)
The code
snippet in Listing 2 creates a 5-tuple using the static "Create" method.
The tuple is a set of 5 data types including three strings, one int, and one
double data type.
1.
// Create a 5-tuple
2.
var pubAuthor = Tuple.Create("Mahesh Chand", "Graphics Programming with GDI+", "Addison Wesley", 2004, 49.95);
3.
4.
System.Console.WriteLine("Author {0} wrote his fourth book titled {1} for {2} in {3}. Price: {4}", pubAuthor.Item1, pubAuthor.Item2, pubAuthor.Item3, pubAuthor.Item4, pubAuthor.Item5);
5. Return Tuples
6. A tuple can be used to return a data set as a
single variable of a method. The code snippet in Listing 6 returns a tuple with
3 values.
7.
public static Tuple<string, string, int> GetTupleMethod()
8.
{
9.
// Create a 3-tuple and return it
10.
var author = new Tuple<string, string, int>(
11.
"Mahesh Chand", "Programming C#", 2002);
12.
return author;
13.
}
The code snippet in Listing 7 calls the
method, gets a tuple, and reads its values.
1.
var author2 = TupleSamples.GetTupleMethod();
2.
Console.WriteLine("Author:{0}, Title:{1}, Year:{2}.", author2.Item1, author2.Item2, author2.Item3);
**Publisher and subscriber:
Delegates
Delegates holds the reference of the Method. It specifies the signature of a
method, and when you have a delegate instance, you can make a call to it as if
it was a method with the same signature.
Events
Everyone is waiting for their salaries, so debit of your salary into your
account is any event. The triggers on 31st or 30th in IT industry of each
month. And we are the subscribers who have been paid for their work or efforts.
Here is our main content:
Three main actors of Publisher and Subscriber pattern:
- The Event: Salary Debited in your account in an event “SalaryDebited”.
- The Publisher : The event is published by the “Organization”
class.
- The Subscriber: Each Employee subscribe to “SalaryDebited”
event.
Assignment
Let's say we have Windows Form (UserForm) and we have a Grid on our “UserForm”.
Again we have one “UserControl” and on UC we have one button.
Now what my job is, on click of button I need to fill the Grid on user form.
So in our case the Publisher is User control and Subscriber is windows form.
Output
- This is our form and its
description. We are adding control (PopulateGrid) on Panel.
- Grid Populated with data on
button click:
**Enum:
An enumeration is used in
any programming language to define a constant set of values. In
C#, enum is a value type data type. The enum is used to declare a list of named
integer constants. It can be defined using the enum keyword
directly inside a namespace, class, or structure. The enum is used to give a
name to each constant so that the constant integer can be referred using its
name.
the
first member of an enum has the value 0 and the value of each successive enum
member is increased by 1
enumweekdays
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
Console.WriteLine((int)weekdays.Wednesday)=>answer
2
enumweekdays
{
Monday=2,
Tuesday=9,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
Console.WriteLine((int)weekdays.Wednesday)=>answer
10
1. The
enum is a set of named constant.
2. The
value of enum constants starts from 0. Enum can have value of any valid numeric
type.
3. String
enum is not supported in C#.
4. Use of
enum makes code more readable and manageable
**struct:
A
structure is a value type that can contain constructors, constants, fields,
methods, properties, indexers, operators, events and nested types. A structure can
be defined using the structkeyword.
publicstructDiscounts
{
publicint Cloths { get; set; }
publicint HomeDecor { get; set; }
publicint Grocery { get; set; }
}
Initialize Structure:
Inside mai
classProgram
{
staticvoid Main(string[] args)
{
Discounts saleDiscounts = newDiscounts();
saleDiscounts.Cloths =
10;
saleDiscounts.HomeDecor
= 5;
saleDiscounts.Grocery =
2;
}
A
struct is a value type so it is faster than a class object. Use struct whenever
you want to just store the data. Generally structs are good for game
programming. However, it is easier to transfer a class object than a struct. So
do not use struct when you are passing data across the wire or to other
classes.
Characteristics of Structure:
- Structure
can include constructors, constants, fields, methods, properties,
indexers, operators, events & nested types.
- Structure
cannot include default constructor or destructor.
- Structure
can implement interfaces.
- A
structure cannot inherit another structure or class.
- Structure
members cannot be specified as abstract, virtual, or protected.
- Structures
must be initialized with new keyword in order to use it's properties,
methods or events.
Difference between Struct and Class:
- Class
is reference type whereas struct is value type
- Struct
cannot declare a default constructor or destructor. However, it can have
parametrized constructors.
- Struct
can be instasntiated without the new keyword. However, you won't be able
to use any of its methods, events or properties if you do so.
- Struct
cannot be used as a base or cannot derive another struct or class.
Points to Remember :
1. Structure is a value
type and defined using struct keyword.
2. Structure can be
initialized with or without new keyword.
3. Structure must be
initialized with new keyword to use its' properties, methods
and events.
4. Example:
Structure
5. structPoint
6. {
7. privateint _x, _y;
8.
9. publicint x, y;
10.
11. publicstaticint X, Y;
12.
13. publicint XPoint {
14. get
15. {
16. return _x;
17. }
18.
19. set
20. {
21. _x = value;
22. PointChanged(_x);
23. }
24. }
25.
26. publicint YPoint
27. {
28. get
29. {
30. return _y;
31. }
32. set
33. {
34. _y = value;
35. PointChanged(_y);
36. }
37. }
38.
39. publiceventAction<int> PointChanged;
40.
41. publicvoid PrintPoints()
42. {
43. Console.WriteLine(" x: {0}, y: {1}",
_x, _y);
44. }
45.
46. publicstaticvoid StaticMethod()
47. {
48. Console.WriteLine("Inside Static method");
49. }
50.}
Initialize Structure using new keyword:
classProgram
{
staticvoid StructEventHandler(int point)
{
Console.WriteLine("Point changed to
{0}", point);
}
staticvoid Main(string[] args)
{
Point.StaticMethod();
Point p = newPoint();
p.PointChanged += StructEventHandler;
p.XPoint = 123;
p.PrintPoints();
}
}
Base
Keyword:
The base keyword is used to refer to the base
class when chaining constructors or when you want to access a member (method,
property, anything) in the base class that has been overridden or hidden in the
current class. For example,
class A {
protectedvirtualvoidFoo() {
Console.WriteLine("I'm
A");
}
}
class B : A {
protectedoverridevoidFoo() {
Console.WriteLine("I'm
B");
}
publicvoidBar() {
Foo();
base.Foo();
}
}
With these
definitions,
new B().Bar();
would output
I'm B
I'm A
1.
**Indexer :
C# introduces a new concept known as Indexers which are used for
treating an object as an array. The indexers are usually known as smart arrays
in C#. They are not essential part of object-oriented programming.
- Indexer Concept is object act
as an array.
- Indexer an object to be indexed
in the same way as an array.
- Indexer modifier can be
private, public, protected or internal.
- The return type can be any
valid C# types.
- Indexers in C# must have at
least one parameter. Else the compiler will generate a compilation error.
- Indexers are always created
with this keyword.
- Parameterized property are
called indexer.
- Indexers are implemented
through get and set accessors for the [ ] operator.
- ref and out parameter modifiers
are not permitted in indexer.
- The formal parameter list of an
indexer corresponds to that of a method and at least one parameter should
be specified.
- Indexer is an instance member
so can't be static but property can be static.
- Indexers are used on group of
elements.
- Indexer is identified by its
signature where as a property is identified it's name.
- Indexers are accessed using
indexes where as properties are accessed by names.
- Indexer can be overloaded.
- using System;
- namespace Indexer_example1
- {
- class Program
- {
- class IndexerClass
- {
- private string[] names = new string[10];
- public string this[int i]
- {
- get
- {
- return names[i];
- }
- set
- {
- names[i] = value;
- }
- }
- }
- static void Main(string[] args)
- {
- IndexerClass Team = new IndexerClass();
- Team[0] = "Rocky";
- Team[1] = "Teena";
- Team[2] = "Ana";
- Team[3] = "Victoria";
- Team[4] = "Yani";
- Team[5] = "Mary";
- Team[6] = "Gomes";
- Team[7] = "Arnold";
- Team[8] = "Mike";
- Team[9] = "Peter";
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine(Team[i]);
- }
- Console.ReadKey();
- }
- }
- }
**
IEnumerable vs IEnumerator
IEnumerable :
IEnumerable
is an interface defining a single method GetEnumerator() that returns an
IEnumerator interface.
This
works for readonly access to a collection that implements that IEnumerable can
be used with a foreach statement.
List<string> Month = newList<string>();
Month.Add("January");
Month.Add("February");
Month.Add("March");
Month.Add("April");
Month.Add("May");
Month.Add("June");
Month.Add("July");
Month.Add("August");
Month.Add("September");
Month.Add("October");
Month.Add("November");
Month.Add("December");
IEnumerable<string> ienumobj = (IEnumerable<string>) Month;
foreach(var months in ienumobj)
{
Console.WriteLine(months);
}
IEnumerator<string> enumertaorobj = (IEnumerator<string>)Month;
//To retrieve all the items from the above IEnumerator object, we
cannot use foreach loop instead of that we need to invoke MoveNext() Boolean
method.
while (enumertaorobj.MoveNext())
{
Console.WriteLine(enumertaorobj.Current);
}
*Relation:
The
IEnumerable interface actually uses IEnumerator. The main reason to create an
IEnumerable is to make the syntax shorter and simpler.
If you
go to the definition of the IEnumerable<T> interface, you will see this
interface has a method GetEnumerator() that returns an IEnumerator object back.
//
// Summary:
// Exposes the
enumerator, which supports a simple iteration over a collection of
// a specified type.To
browse the .NET Framework source code for this type, see
// the Reference Source.
//
// Type parameters:
// T:
// The type of objects
to enumerate.This type parameter is covariant. That is, you
// can use either the
type you specified or any type that is more derived. For more
// information about
covariance and contravariance, see Covariance and Contravariance
// in Generics.
[TypeDependencyAttribute("System.SZArrayHelper")]
publicinterfaceIEnumerable<outT> : IEnumerable
{
//
// Summary:
// Returns an enumerator
that iterates through the collection.
//
// Returns:
// An enumerator that
can be used to iterate through the collection.
IEnumerator<T> GetEnumerator();
}
In
short, this IEnumerable uses IEnumerator internally.
Differences:
The main difference between IEnumerable and IEnumerator
is an IEnumerator retains its cursor's current state. So, IEnumerator retains
its cursor state.
classProgram
{
staticvoid iEnumeratorMethodOne(IEnumerator<string> i)
{
while (i.MoveNext())
{
Console.WriteLine(i.Current);
if(i.Current== "June")
{
iEnumeratorMethodTwo(i);
}
}
}
staticvoid iEnumeratorMethodTwo(IEnumerator<string> j)
{
Console.WriteLine("second method start");
while (j.MoveNext())
{
Console.WriteLine(j.Current); => july and onwards so it maintain
cursor state.
}
}
staticvoid Main(string[] args)
{
List<string> Month = newList<string>();
Month.Add("January");
Month.Add("February");
Month.Add("March");
Month.Add("April");
Month.Add("May");
Month.Add("June");
Month.Add("July");
Month.Add("August");
Month.Add("September");
Month.Add("October");
Month.Add("November");
Month.Add("December");
iEnumeratorMethodOne(Month.GetEnumerator());
* Constant and ReadOnly and Static
Constant
Constant fields or local variables must be assigned
a value at the time of declaration and after that they cannot be modified. By
default constant are static, hence you cannot define a constant type as static.
·
Could be declared within functions
1. publicconstint X =10;
A const
field is a compile-time constant. A constant field or local variable can be
initialized with a constant expression which must be fully evaluated at compile
time.
1. voidCalculate(int Z)
2. {
3. constint X =10, X1 =50;
4. constint Y = X + X1;//no error, since its evaluated a compile time
5. constint Y1 = X + Z;//gives error, since its evaluated at run time
6. }
You can
apply const keyword to built-in value types (byte, short, int, long, char,
float, double, decimal, bool), enum, a string literal, or a reference type
which can be assigned with a value null.
1. constMyClass obj1 = null;//no error, since its evaluated a compile time
2. constMyClass obj2 =newMyClass();//gives error, since its evaluated at run time
Constants
can be marked as public, private, protected, internal, or protected internal
access modifiers.
Use the
const modifier when you sure that the value a field or local variable would not
be changed
ReadOnly
A readonly
field can be initialized either at the time of declaration or with in the
constructor of same class. Therefore, readonly fields can be used for run-time
constants.
1. classMyClass
2. {
3. readonly int X =10;// initialized at the time of declaration
4. readonly int X1;
5.
6. publicMyClass(int x1)
7. {
8. X1 = x1;// initialized at run time
9. }
10. }
Explicitly,
you can specify a readonly field as static since, like constant by default it
is not static. Readonly keyword can be apply to value type and reference type
(which initialized by using the new keyword) both. Also, delegate and event
could not be readonly.
Use the
readonly modifier when you want to make a field constant at run time.
**Static ReadOnly: A Static
Readonly type variable's value can be assigned at runtime or assigned at
compile time and changed at runtime. But this variable's value can only be
changed in the static constructor. And cannot be changed further. It can change
only once at runtime. Let's understand it practically
Static:
The static
keyword is used to specify a static member, which means static members are
common to all the objects and they do not tied to a specific object. This
keyword can be used with classes, fields, methods, properties, operators,
events, and constructors, but it cannot be used with indexers, destructors, or
types other than classes.
1. classMyClass
2. {
3. staticint X =10;
4. int Y =20;
5. publicstaticvoidShow()
6. {
7. Console.WriteLine(X);
8. Console.WriteLine(Y);//error, since you can access only static members
9. }
10. }
Key points about Static keyword
1.
If the static keyword is applied to a class, all the members of
the class must be static.
2.
Static methods can only access static members of same class.
Static properties are used to get or set the value of static fields of a class.
3.
Static constructor can't be parameterized. Access modifiers can
not be applied on Static constructor, it is always a public default constructor
which is used to initialize static fields of the class.
**Thread vs Process vs task:
A task is a set of program instructions that are loaded in
memory.
All running instance of Program is called process.
A program in Simple terms
can be described as any executable file. A programme can have n number of
process.
A Thread is commonly
described as a lightweight process. 1 process can have N
threads
ð
A programme(msword)
can have multiple process (creating new document, Editing existing document and
opening another document)
And one process can have multiple threads(ui thread,thred for
saving images, thread for changing
fonts).
Task internally uses threads
so task is wrapper on threading.
A program in
Simple terms can be described as any executable file. Basically it contains
certain set of instructions written with the intent of carrying out a specific
operation. It resides in Memory & is a passive entity which doesn’t go away
when system reboots.
Any
running instance of a program is called as process or it can
also be described as a program under execution. 1 program can
have N processes. Process resides in main memory & hence
disappears whenever machine reboots. Multiple processes can be run in parallel
on a multiprocessor system.
A Thread is commonly described as a lightweight
process. 1 process can have N threads. All
threads which are associated with a common process share same memory as
of process.The essential difference between a thread and a process is the
work that each one is used to accomplish. Threads are being used for small
& compact tasks, whereas processes are being used for more heavy tasks.
One
major difference between a thread and a process is that threads within the
same process consume the same address space, whereas different processes
do not. This allows threads to read from and write to the common shared
and data structures and variables, and also increases ease
of communication between threads. Communication between two or more
processes – also known as Inter-Process Communication i.e. IPC – is quite
difficult and uses intensive resources.
Tasks are
very much similar to threads, the difference is that they generally do not
interact directly with OS. Like a Thread Pool, a task does not create its
own OS thread. A task may or may not have more than one thread internally.
If you
want to know when to use Task and when to use Thread: Task is simpler to use
and more efficient that creating your own Threads. But sometimes, you need more
control than what is offered by Task. In those cases, it makes more sense to
use Thread directly.
The bottom line is that Task is almost always the best option;
it provides a much more powerful API and avoids wasting OS threads.The only
reasons to explicitly create your own Threads in modern code are setting
per-thread options, or maintaining a persistent thread that needs to maintain
its own identity.
TPL:
Without TPL:
·
Inside using System.Threading.Tasks;
·
TPL helps in asynchnous programming
and it multiple thread on all the processer utilizations.
·
Thread may run single processer but TPL RUN on different processer
·
classProgram
{
publicstaticvoid runmilionitertion()
{
string x = "";
for(int index=0; index<100000;index++)
{
x = x + "s";
Console.WriteLine(x);
}
}
staticvoid Main(string[] args)
{
Thread th = newThread(Program.runmilionitertion);
th.Start();
Console.ReadLine();
}
}
*with TPL:
classProgram
{
publicstaticvoid runmilionitertion()
{
string x = "";
for(int index=0; index<1000000;index++)
{
x = x + "s";
Console.WriteLine(x);
}
}
staticvoid Main(string[] args)
{
Parallel.For(0, 1000000, x =>Program.runmilionitertion());
Console.ReadLine();
}
}
Multithreaded
programming can be a real pain. In the old days, we have to deal with creating
and managing threads. It was a chore. However, the .NET Task Parallel Library
(TPL) makes programming asynchronous operations, the usual work of threads, a
lot less painful and a lot more fun.
This is a
Down and Dirty article. The goal here is to give you the basics you need to be
operational in TPL programming without a lot of theoretical overhead. The
article is meant to be fast and simple. You're going get some basic concepts
while looking a lot of code. Then, if you feel inspired, you can look to other
references to get the details you need to dive more deeply into TPL.
To get
full benefit from reading this article, we expect that you can read and program
in C#. Also, we assume that you understand the basics of lambda expressions and generics. If you
have these basics, you are ready to get down and dirty.
Understanding
a Task
Before you
go anywhere with TPL, you need to understand the shortcomings of .NET thread
programming. The benefit of using multiple threads is that you to do concurrent
programming. Methods in a single threaded environment run sequentially. In a
multithreaded environment, methods can run simultaneously (see Figure 1).
Selecting a Workload Automation Tool
Figure 1: Methods
run sequentially in a single thread; concurrently in a multithreaded
environment
Where
threading becomes really powerful is on computers having many cores. (Think of
a core as a CPU.) Theoretically, when you create multiple threads, the
operating system is supposed to assign each thread to a core. In reality, in
.NET when you use a Thread object, sometimes the thread runs on a distinct core
and sometimes it doesn't (see Figure 2).
Figure 2: Sometimes,
a .NET Thread will not run on its own thread.
TPL makes
it so that you can do reliable multithread programming across multiple cores.
All
Cores, All the Time
The Task
Parallel Library introduced in .NET 4.5 has automagic that allows you to spawn
threads that really do get assigned to a distinct core (see Figure 3).
Figure 3: The
Task Parallel Library ensures that threads get assigned to cores, when
available.
The way
that .NET and the Task Parallel Library fixed this thread issue is to create a
thread mechanism called a Task. You can
think of Task as an asynchronous operation. Not only do you get the execution
isolation that comes with threading, you get functionality that makes
programming threads a lot easier.
Working
with a Task
As
mentioned earlier, a Task describes an asynchronous operation. When you start a
Task, you'll pass the Task a lambda expression that
indicates the behavior the Task is to execute. That lambda expression can go to
a named method or an anonymous method.
There are
a few ways to create and run a Task. One way is to use the static method Task.Run(). The
method SendDefaultMethod() in
the class DownAndDirtyMessenger shown
in Listing 1 illustrates how to use Task.Run. (The class, DownAndDirtyMessenger, is the
code example that we'll use throughout this article.)
The
method SendDefaultMessage() uses Task.Run() to
start a Task that runs the method SimpleSend(), asynchronously. Task.Run() takes
as an argument a lambda expression that goes to SimpleSend(). Also, the
Task that is created is returned by the method, SendDefaultMessage(). This
Task is passed to any code that calls DownAndDirtyMessenger.SendDefaultMessage(). Working
with the Task returned by SendDefaultMessage() is addressed later in this
article.
1. namespace reselbob.demos.tpl
2. {
3. publicclassDownAndDirtyMessenger
4. {
5.
6. privatestring _defaultMessage ="Default Message";
7.
8. privatevoidSimpleSend()
9. {
10. Console.WriteLine(_defaultMessage);
11. }
12.
13.
14. publicTaskSendDefaultMessage()
15. {
16. returnTask.Run(()=>SimpleSend());
17. }
18.
19. .
20. .
21. .
22. }
Listing
1: You create a Task with a lambda expression.
Using Anonymous Methods in a Task
Another
way start a Task is by using a Task.Factory, as shown in Listing 2.
1. publicTask<string>SendMessage(string message,
2. int secondsToWait =1)
3. {
4.
5. Task<string> task =Task.Factory.StartNew(()=>
6. {//start anonymous method here
7. var msg = message;
8.
9. if(string.IsNullOrEmpty(message))
10. msg = _defaultMessage;
11. var inTime =DateTime.Now;
12. Thread.Sleep(secondsToWait *1000);
13. var rtn =string.Format("I am sending this Message:{0}
14. from within the Tasks, Time in: {1}, Time out: {2}",
15. msg, inTime.ToString(_fmt),
16. DateTime.Now.ToString(_fmt));
17. Console.WriteLine(rtn);
18. return rtn;//return the string as the TResult
19. });
20. return task;
21. }
Listing
2: You can define the entire behavior of a given Task within
the lambda expression argument.
Let take a
close look at two parts of Listing 2, the method signature and the execution of
an anonymous method that the lambda expression goes to.
First, the
method signature.
1. publicTask<string>SendMessage(string message,
2. int secondsToWait =1){......}
Notice,
please, that SendMessage() returns
a generic, Task<string>. What's
really going here is that .NET is saying that the method SendMessage() is
going to return a Task with a TResult of type, string. What is a TResult? Hang
tight; we'll get to TResult shortly.
Let's move
on the second part, the anonymous method used in the lambda expression. Whereas
in Listing 1, we created a Task that had a lambda expression that goes to a
named method, SimpleSend(), in
Listing 2 the lambda expression goes to an anonymous method. Also, the
anonymous method returns a string. This returned string is the TResult that is defined as the return type of SendMessage(), the
type, Task<string>.
Let's take
a closer look at TResult.
Working with TResult
Let's look
at a simple method signature:
1. publicintAddNumbers(int x,int y){return x +y;};
It's
pretty straightforward. We have a method, AddNumbers(), that
returns a simple type, int.
However, when
we deal with a method that returns a Task object, we have to do things a bit
differently.
The way
you define a Task that returns a result is:
1. Task<TResult>
WHERE TResult
is the type returned by the asynchronous operation.
Let's look
again at the method signature for SendMessage().
1. publicTask<string>SendMessage(string message,
2. int secondsToWait =1)
Remember,
that a Task represents an asynchronous operation. So, the return from SendMessage() is a
reference to the Task it created. But, if we remember back to Listing 2, the
anonymous method in SendMessage() returned
a string. How can this happen, a method having two return types? Well, not
really. Remember, the return type for SendMessage() is: Task<string>. It's
generic in which the string is the TResult of the Task.
So, when
we declare a return type of Task<string>, what we are saying is
"return a Task with a TResult of type, string." The property,
Task.Result, is where the TResult lives. Listing 3 shows how we can access the
TResult of a Task, when used in a ContinueWith() method. (ContinueWith() is a
method of a Task that gets executed when the Task completes.)
1. var messenger =newDownAndDirtyMessenger();
2. var task = messenger.SendMessage(null);
3. task.ContinueWith((t)=>{
4. Console.WriteLine("The TResult value is: "+
5. t.Result);
6. });
Listing
3: TPL automagically passes the Task into the ContinueWith()
lambda expression as the parameter, t
One of the
nice things about TResult is that can create a custom class to be used as your
TResult type. Listing 4 shows a class, MessengerResult, that represents a custom class
for the TResult that is used by the demonstration class, DownAndDirtyMessenger.
1. usingSystem;
2.
3. namespace reselbob.demos.tpl
4. {
5.
6. publicenumSendStatus
7. {
8. Success,
9. Fail
10. }
11.
12. publicclassMessengerResult
13. {
14. publicstringMessage{get;set;}
15. publicDateTimeSendTime{get;set;}
16. publicDateTimeReceivedTime{get;set;}
17. publicSendStatusSendStatus{get;set;}
18. }
19. }
Listing
4: You can create a custom class for your TResult
Listing 5
shows you how to use a custom class as TResult. The method, SendMessageEx(), declares
a return type of Task<MessengerResult>. The
class, MessengerResult, is the
TResult of the returned Task.
1. publicTask<MessengerResult>SendMessageEx(string message,
2. int secondsToWait =1)
3. {
4. Task<MessengerResult> task =Task.Factory.StartNew(()=>
5. {
6. var msg = message;
7. if(string.IsNullOrEmpty(message)) msg = _defaultMessage;
8. var inTime =DateTime.Now;
9. // put in some time-consuming behavior
10. Thread.Sleep(secondsToWait *1000);
11. var outTime =DateTime.Now;
12. var rtn =string.Format(msg);
13. returnnewMessengerResult{Message= msg,ReceivedTime=
14. inTime,SendTime= outTime };
15. });
16. return task;
17. }
Listing
5: Using a custom class as a TResult
Let's take
a closer look at Task.ContinueWith() now.
Using Task.ContinueWith()
There are
a number of properties and methods that
allow you work with a given Task(see Figure 4). The method that allows you to
react to a Task once it completes is ContinueWith().
Figure 4: A
Task.ContinueWith() allows you to react to a Task's completion
Task.ContinueWith()
is very polymorphic, with a lot of argument permutations. The one that we are
interested in is:
1. publicTaskContinueWith(
2. Action<Task> continuationAction
3. )
The
variation shown above means that you can use an anonymous method within
Task.ContinueWith(). Listing 6 shows an anonymous method within task.ContinueWith((t) => {....}.
1. var messenger =newDownAndDirtyMessenger();
2. Task<MessengerResult> task =
3. messenger.SendMessageEx("This is a secret message");
4. task.ContinueWith((t)=>{
5. var fmt ="H:mm:ss:fff";
6. Console.WriteLine("Message:{0} from within the Tasks,
7. Time in: {1}, Time out: {2}, Status: {3}",
8. t.Result.Message,
9. t.Result.ReceivedTime.ToString(fmt),
10. t.Result.SendTime.ToString(fmt),
11. t.Result.SendStatus.ToString());
12. });
Listing
6: Using an anonymous method in Task.ContinueWith();
Notice,
please, that the t passed
as a parameter in the lambda expression represents the Task associated with the
method, ContinueWith(). Because we can get at the Task, we can get the to
TResult by way of the property, t.Result.
Now, here
is where it gets really interesting. Please remember that, in Listing 6, DownAndDirtyMessenger.SendMessageEx() returns
a Task<MessengerResult>. The
TResult of the Task returned by the method is type, MessengerResult. Thus,
the type of the property, t.Result is MessageResult. We
access the properties of the type, MessageResult, as follows:
1. t.Result.ReceivedTime.ToString(fmt),
2. t.Result.SendTime.ToString(fmt)
3. t.Result.SendStatus.ToString());
The
important thing to take away from all this is that Task.ContinueWith() allows
you to react to a Task upon completion and that we can use a custom class as a
TResult to get result information from a Task.
Iteration
with Parallel Loops
The Task
Parallel Library contains the class, Parallel. Parallel allows you to do
asynchronous looping. We're going to look at three methods of the Parallel
class.
·
Parallel.Invoke()
·
Parallel.For()
·
Parallel.ForEach()
Each of
these methods is highly polymorphic, with lots of parameterization. So for now,
we're going to take a simple look at using each. After all, this is a Dirty and
Dirty article, not a Deep and In-Depth.
Parallel.Invoke()
Parallel.Invoke()
allows you to invoke methods asynchronously. Listing 7 shows you how to use
Parallel.Invoke() to execute five methods simultaneously. Parallel.Invoke() is
wrapped up in a method, SendSpam().
1. privatestring _fmt ="H:mm:ss:fff";
2. privatevoidSimpleSend(string message)
3. {
4. Console.WriteLine(message +" at "+
5. DateTime.Now.ToString(_fmt));
6. }
7.
8. publicvoidSendSpam()
9. {
10. Parallel.Invoke(
11. ()=>SimpleSend("Moe"),
12. ()=>SimpleSend("Larry"),
13. ()=>SimpleSend("Curly"),
14. ()=>SimpleSend("Shemp"),
15. ()=>SimpleSend("Joe Besser"));
16. }
Listing
7: Parallel.Invoke takes an array of lambda expressions
asynchronously
We call
SendSpam() as follows:
1. var messenger =newDownAndDirtyMessenger();
2. messenger.SendSpam();
The return
of the call is a series of Console.Write statements, the output of which is
shown below.
1. Moe at 15:34:39:478
2. Larry at 15:34:39:482
3. Curly at 15:34:39:482
4. Shemp at 15:34:39:482
5. JoeBesser at 15:34:39:483
Notice
that the timestamps of the line of output indicate that the run was almost
simultaneous. Yes, we have two outliers. The machine that this code is running
on is a two-core machine. So, we might chalk up the slowness of the two
outliers to have maxed out the capacity of the machine's CPU.
Parallel.For()
Parallel.For()
allows you to run items items in a for loop asynchronously. The syntax of the
Parallel.For() statement is similar to a standard for loop, except the
incrementer is implied, so that no i++ is needed. Listing 8 shows you Parallel.For() in action.
1. publicvoidSendMessages(string[] messages)
2. {
3. Parallel.For(
4. 0, messages.Length, i =>
5. {SimpleSend(messages[i]);});
6. }
Listing
8: Parallel.For() allows you to iterate over an array
asynchronously
The
Parallel.For() in Listing 8 is wrapped in a method, SendMessages(string[]
messages).
Here is an
example of calling the Parallel.For() by way of SendMessages(string[]
messages).
1. var messenger =newDownAndDirtyMessenger();
2. string[] messages ={"Hello There!","Goodby There!",
3. "Do you know the meaning of life?"};
4. messenger.SendMessages(messages);
The
outputs are shown below. Notice again that the method, SimpleSend(...), which
is called in the Parallel.For executes almost simultaneously. The lag is
probably due to my funky, old, two-core machine.
1. HelloThere! at 15:36:51:401
2. GoodbyThere! at 15:36:51:
3. Do you know the meaning of life? at 15:36:51:405
Parallel.ForEach()
Parallel.ForEach
allows you to iterate through collections. Listing 9 shows SendMessages(IEnumerable<string>
messages), which is a wrapper for Parallel.ForEach(...).
1. publicvoidSendMessages(IEnumerable<string> messages)
2. {
3. Parallel.ForEach(messages, message =>
4. {
5. Console.WriteLine(message +" at "+
6. DateTime.Now.ToString(_fmt));
7. });
8. }
Listing
9: Parallel.ForEach(...) iterates over collections.
We call
SendMessage like so:
1. var messenger =newDownAndDirtyMessenger();
2. IEnumerable<string> messages =newList<string>{"Hi Moe",
3. "Hi Larry","Hi Curly","Hi Shemp","Hi Joe Besser"};
4. messenger.SendMessages(messages);
And the
output is shown below:
1. HiMoe at 15:39:19:682
2. HiLarry at 15:39:19:685
3. HiCurly at 15:39:19:686
4. HiShemp at 15:39:19:686
5. HiJoeBesser at 15:39:19:686
Again,
near simultaneous calls, weirdness due to my machine.
Putting
It All Together
This has
been a typical Down and Dirty Session. We've covered a lot. You learned how to
get up and running using the Task object and you looked at using the Parallel
class to iterate asynchronously.
There is
little doubt about it, the Task Parallel Library makes asynchronous programming
in .NET a whole lot easier than it was in years prior. Still, the technology is
broad. You'll need some time get accustomed to it. I hope that you give
yourself the time because, once you do, a whole new way of thinking in code
will open up to you.
Get the
Code
***thread Pool and Task difference is very simple. To understand task you should
know about the thread pool:
:
Thread Pool is basically
help to manage and reuse the free threads. In other words a threadpool is the
collection of background thread.
Simple definition of task can be:
Task work
asynchronously manages the the unit of work. In easy words Task doesn’t create
new threads. Instead it efficiently manages the threads of a threadpool.Tasks
are executed by TaskScheduler, which queues tasks onto threads.