MS Net
MS Net
Framework Basics
CTS:-
Common Type System (CTS) describes the datatypes that can be used by managed code.
CTS defines how these types are declared, used and managed in the runtime. It facilitates
cross-language integration, type safety, and high-performance code execution. The rules
defined in CTS can be used to define your own classes and values.
CTS deals with the data type. So here we have several languages and each and every
language has its own data type and one language data type cannot be understandable by
other languages but .NET Framework language can understand all the data types. C# has an
int data type and VB.NET has Integer data type. Hence a variable declared as an int in C# and
Integer in VB.NET, finally after compilation, uses the same structure Int32 from CTS.
Note
All the structures and classes available in CTS are common for all .NET Languages and the
purpose of these is to support language independence in .NET. Hence it is called CTS.
Sunbeam Institute of Information Technology Pune and Karad
The Common Language Runtime (CLR) is a core component of .NET Framework that manages
the execution and the lifecycle of all .NET applications (code). It provides various services,
including automatic memory management, exception handling, security, and type safety. When
a .NET application is compiled, it generates an intermediate language code called Common
Intermediate Language (CIL). The CLR is responsible for translating this CIL into machine code
and managing the execution of the resulting program. The CLR also provides a platform for
interoperability between different programming languages that target the .NET Framework. This
means that a program written in one .NET language can easily use libraries written in another
.NET language. Overall, the CLR is an essential component of the .NET Framework that
enables developers to create robust, secure, and interoperable applications.
As part of the Microsoft .NET Framework, the Common Language Runtime (CLR) is
the programming (Virtual Machine component) that manages the execution of
programs written in any language that uses the .NET Framework, for example, C#,
VB.Net, F# and so on.
Programmers write code in any language, including VB.Net, C#, and F#, when they
compile their programs into an intermediate form of code called CLI in a portable
execution file (PE) that can be managed and used by the CLR. Then the CLR converts it
into machine code to be will be executed by the processor.
The information about the environment, programming language, its version, and what
class libraries will be used for this code are stored as metadata with the compiler that
tells the CLR how to handle this code.
The CLR allows an instance of a class written in one language to call a method of the
class written in another language.
Sunbeam Institute of Information Technology Pune and Karad
As you can see from the above diagram, the CLR provides several services.
Performance improvements.
The ability to easily use components developed in other languages.
A class library provides extensible types.
Language features such as inheritance, interfaces, and overloading for object-
oriented programming.
Support for explicit free threading that allows the creation of multithreaded,
scalable applications.
Support for structured exception handling.
Support for custom attributes.
Garbage collection.
Use of delegates instead of function pointers for increased type safety and
security.
IL Code:-
Summery
The .NET assembly is the standard for components developed with the Microsoft.NET. Dot NET
assemblies may or may not be executable, i.e., they might exist as the executable (.exe) file or
dynamic link library (DLL) file. All the .NET assemblies contain the definition of types, versioning
information for the type, meta-data, and manifest. The designers of .NET have worked a lot on
the component (assembly) resolution.
An assembly can be a single file or it may consist of the multiple files. In the case of multi-file,
there is one master module containing the manifest while other assemblies exist as non-
manifest modules. A module in .NET is a subpart of a multi-file .NET assembly. Assembly is
one of the most interesting and extremely useful areas of .NET architecture along with
reflections and attributes.
1. private
2. shared
3. satellite
Private Assembly
Private assembly requires us to copy separately in all application folders where we want to use
that assembly’s functionalities; without copying, we cannot access the private assembly features
and power. Private assembly means every time we have one, we exclusively copy into the BIN
folder of each application folder.
Public Assembly
Public assembly is not required to copy separately into all application folders. Public assembly is
also called Shared Assembly. Only one copy is required in system level, there is no need to
copy the assembly into the application folder.
Public assembly should install in GAC.
Shared assemblies (also called strong named assemblies) are copied to a single location
(usually the Global assembly cache). For all calling assemblies within the same application, the
same copy of the shared assembly is used from its original location. Hence, shared assemblies
Sunbeam Institute of Information Technology Pune and Karad
are not copied in the private folders of each calling assembly. Each shared assembly has a four-
part name including its face name, version, public key token, and culture information. The public
key token and version information makes it almost impossible for two different assemblies with
the same name or for two similar assemblies with a different version to mix with each other.
When the assembly is required for more than one project or application, we need to make the
assembly with a strong name and keep it in GAC or in the Assembly folder by installing the
assembly with the GACUtil command.
Satellite Assembly
Satellite assemblies are used for deploying language and culture-specific resources for an
application.
The most important part of the .NET Framework is the .Net Common Language Runtime (CLR)
also called .Net Runtime in short. It is a framework layer that resides above the Operating
System and handles/manages the execution of the .NET applications. Our .Net programs don't
directly communicate with the Operating System but through CLR.
When we compile our .Net Program using any .Net compliant language like (C#, VB.NET,
C++.NET) it does not get converted into the executable binary code but to an intermediate code,
called MSIL or IL in short, understandable by CLR. MSIL is an OS and H/w independent code.
When the program needs to be executed, this MSIL or intermediate code is converted to binary
Sunbeam Institute of Information Technology Pune and Karad
executable code, called native code. The presence of IL makes it possible for the Cross-
Language Relationship as all the .Net compliant languages produce the similar standard IL
code.
When our IL compiled code needs to be executed, CLR invokes JIT compilers which compile
the IL code to native executable code (.exe or .dll) for the specific machine and OS. JITers in
many ways is different from traditional compilers as they, as their name suggests, compile the IL
to native code only when desired e.g., when a function is called, IL of function's body is
converted to native code; just in time of need. So, the part of code that is not used by a
particular run is not converted to native code. If some IL code is converted to native code then
the next time when it's needed to be used, the CLR uses the same copy without re-compiling.
So, if a program runs for some time, then it won't have any just in a time performance penalty.
As JITers are aware of processor and OS exactly at runtime, they can optimize the code
extremely efficiently resulting in very robust applications. Also, since JITer knows the exact
current state of executable code, they can also optimize the code by in-lining small function calls
(like replacing body of small function when its called in a loop, saving the function call time).
Although Microsoft stated that C# and .Net are not competing with languages like C++ in
efficiency, speed of execution, JITers can make your code even faster than C++ code in some
cases when the program is run over an extended period of time (like web-servers).
.NET Framework provides a huge set of Framework (or Base) Class Library (FCL) for common,
usual tasks. FCL contains thousands of classes to provide them access to Windows API and
common functions like String Manipulation, Common Data Structures, IO, Streams, Threads,
Security, Network Programming, Windows Programming, Web Programming, Data Access, etc.
It is simply the largest standard library ever shipped with any development environment or
programming language. The best part of this library is they follow extremely efficient OO design
(design patterns) making their access and use very simple and predictable. You can use the
classes in FCL in your program just as you use any other class and can even apply inheritance
and polymorphism on these.
Earlier we used the term '.NET Compliant Language' and stated that all the .NET compliant
languages can make use of CLR and FCL. But what makes a language '.NET compliant
language'? The answer is the Common Language Specification (CLS). Microsoft has released a
small set of specifications that each language should meet to qualify as a .NET Compliant
Language. As IL is a very rich language, it is not necessary for a language to implement all the
IL functionality, rather it meets the small subset of it, CLS, to qualify as a .NET compliant
language, which is the reason why so many languages (procedural and OO) are now running
under .Net umbrella. CLS basically addresses to language design issues and lays certain
standards like there should be no global function declaration, no pointers, no multiple
Sunbeam Institute of Information Technology Pune and Karad
inheritance and things like that. The important point to note here is that if you keep your
code within the CLS boundary, your code is guaranteed to be usable in any other .Net
language.
.NET also defines a Common Type System (CTS). Like CLS, CTS is also a set of
standards. CTS defines the basic data types that IL understands. Each .NET compliant
language should map its data types to these standard data types. This makes it
possible for the 2 languages to communicate with each other by passing/receiving
parameters to/from each other. For example, CTS defines a type Int32, an integral data
type of 32 bits (4 bytes) which is mapped by C# through int and VB.Net through its
Integer data type.
CLR also contains Garbage Collector (GC) which runs in a low-priority thread and
checks for un-referenced dynamically allocated memory space. If it finds some data
that is no more referenced by any variable/reference, it re-claims it and returns the
occupied memory back to the Operating System; so that it can be used by other
programs as necessary. The presence of standard Garbage Collector frees the
programmer from keeping track of dangling data.
C#
Basics
Compilation
Compilation is the process of converting source code into a form that can be executed by a
computer. The C# compiler converts C# source code into a Common Intermediate Language (CIL)
assembly. The CIL assembly is then executed by the Common Language Runtime (CLR).
Roslyn is the open-source compiler platform for C# and Visual Basic.NET developed by Microsoft.
It provides APIs for analyzing and manipulating code, enabling powerful code analysis and
refactoring tools.
To compile a C# program from the command line, you can use the csc.exe compiler. The csc.exe
compiler is located in the .NET Framework installation directory.
Step 1: Open the text editor like Notepad or Notepad++, and write the code that you want to execute.
Now save the file with .cs extension.
// C# program to print Hello World!
using System;
// namespace declaration
namespace HelloWorldApp {
// Class declaration
class Geeks {
// Main Method
static void Main(string[] args)
{
// statement
// printing Hello World!
Console.WriteLine("Hello World!");
csc File_name.cs
If your program has no error, then it will create a filename.exe file in the same directory where you
have saved your program. Suppose you saved the above program as Hello.cs. So you will write csc
Hello.cs on cmd. This will create a Hello.exe file.
Step 3: Now there are two ways to execute the Hello.exe. First, you have to simply type the filename
i.e. Hello on the cmd and it will give the output. Second, you can go to the directory where you saved
your program and there you find filename.exe. You have to simply double-click that file and it will give
the output.
C: \users\Shubham>Hello
Hello world!
C: \users\Shubham>Hello.exe
Hello World!
Types
C# supports a variety of data types, including integers, floating-point numbers, strings, and
Boolean. C# also supports user-defined types, such as classes and struts.
Loops
C# supports three types of loops: for loops, while loops, and do-while loops.
Basic Syntax
EXE
An EXE file is an executable file that can be run on a Windows computer. To create an EXE file from
a C# program, you need to compile the program with the csc.exe compiler.
DLL
A DLL file is a dynamic link library or class library that can be used by other programs. To create a
DLL file from a C# program, you need to compile the program with the csc.exe compiler and specify
the /target: library option.
A class library file is a collection of classes and namespaces in C# without any entry point method
like Main. Once we create a class library file it can be used in the C# project and classes inside it can
be used as required. Class Library makes it convenient to use functionalities by importing DLL inside
the program rather than redefining everything. So, Let’s make our own class library in C#.
Terminologies
Class Library: It is a package or file that contains different namespaces and class definitions that are
used by other programs.
Step 1: Create a New Project in Visual Studio. Once You open visual studio it should open Create
New Project OR You can click on the file and select the new project option. Select C# as language
and then Select Class Library Option. Click Next.
Step 2: On the next screen configure your class library project name. Make sure you give a different
name for the Solution. Then click next.
Step 3: On the next screen select the .NET version. I have selected 7.0. Then click create which will
create a project.
Step 4: Once the Project is created a C# file will already be created with namespace as project name
and class Class1. Let’s add some code inside the class that will print something when the
method sayHello() inside the class is called.
Step 5: After writing the code click on the build in the menu bar and click build geeksforgeeks.
Step 6: If everything is correct you should get build success in the output below the editor.
Step 7: Now the DLL file is created inside the project-folder/bin/Debug/net7.0 folder which can be
used.
Step 8: Let’s create a new project to use this DLL file. For the new project select Console App from
the list and click next.
Step 9: Configure a new project with a name and give the same name for the solution as given for
creating a Class library project OR just select the same folder for a solution.
Step 10: Once the project is created it should have a program.cs file opened. Type the Code inside
the program.cs file. import the DLL file inside the program by putting “using geeksforgeeks” at the
top. Now we can use Class1 inside our program. Call the sayHello() method by creating an object of
Class1.
Step 11: Afterwards we have to add a reference of the DLL file to our project. For that in Solution
Explorer select dependencies under our project name and right-click to select “Add Project
reference”.
Step 12: Now select our Class Library project name from the list. Click Ok. Now we can build our
project.
Step 13: From the menu click build and select build “geeksforgeeksapp” or your console project
name. You should see the build succeeded at the output.
Step 14: Once Build is succeeded right click on Class Library Project from Solution Explorer and
select unload the project. Then click on run without debugging on the sub-menu bar at the top (play
button).
Step 15: You should see a console window opened with say hello message printed.
Step 1: Create a new blank file inside your favourite editor and save it as a “.cs” file with the name
you want for DLL. Add the Code to the file with namespace and class with any method. I have added
the same method as above which prints “Hello From GeeksForGeeks”.
Step 2: Open Command Prompt or Terminal where the CS file is saved. Compile the program with
the CSC compiler and make sure you add the target file as a library which will generate a DLL file. If
there is no error, then you should see a DLL file created inside a folder with the name as the
filename.
Step 3: Now let’s use this DLL. Create another file inside the same folder where DLL is located and
save it as “.cs”. Type your code to use the DLL. I have written the same code as above.
Step 4: Then save the file and compile it with CSC as follows. We have used /r to provide references
for our DLL file.
Step 5: If no error compilation is successful and we can run our program type filename.exe to run the
program. You should see the output printed.
To consume a DLL in an EXE file, you need to add a reference to the DLL file in the EXE project. You
can do this by right-clicking on the References node in the Solution Explorer and selecting Add
Reference.
Console | Convert Class & Methods
Convert class provides different methods to convert a base data type to another base data type. The
base types supported by the Convert class are Boolean, Char, SByte, Byte, Int16, Int32, Int64,
UInt16, UInt32, UInt64, Single, Double, Decimal, DateTime, and String. It also provides methods that
support other conversions. This class is defined under System namespace.
Method Description
Example :
// C# program to illustrate the
// use of ToDecimal(Int16) method
using System;
class GFG {
// Main method
static public void Main()
{
Output:
Elements are:
1
-32768
0
106
-32
convert value is: 1
convert value is: -32768
convert value is: 0
convert value is: 106
convert value is
OOP Concepts
Object-Oriented Programming (OOP) is a programming paradigm based on the concept of "objects,"
which can contain data in the form of fields (attributes or properties) and code in the form of
procedures (methods or functions). C# is a language that fully supports OOP principles. Here are the
key OOP concepts in C#:
Encapsulation:
Encapsulation is the bundling of data (fields) and methods that operate on the data within a single
unit (class).
It helps in hiding the internal state of an object and restricting access to it through public methods.
Inheritance:
Inheritance allows a class (subclass or derived class) to inherit properties and behavior from another
class (superclass or base class).
It promotes code reusability and establishes an "is-a" relationship between classes.
class Animal
{
public void Eat()
{
Console.WriteLine("Animal is eating.");
}
}
class Dog : Animal
{
public void Bark()
{
Console.WriteLine("Dog is barking.");
}
}
Dog myDog = new Dog();
myDog.Eat();
myDog.Bark();
Polymorphism:
Polymorphism allows objects of different types to be treated as objects of a common base type.It
enables methods to be defined in a base class and overridden in derived classes to provide different
implementations.
class Shape
{
public virtual void Draw()
{
Console.WriteLine("Drawing a shape.");
}
}
class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a circle.");
}}
Shape myShape = new Circle();
myShape.Draw(); // Outputs: Drawing a circle.
Abstraction:
Abstraction is the process of hiding the complex implementation details and exposing only the
necessary features of an object.
It allows you to focus on what an object does rather than how it does it.
Interfaces:
Interfaces define a contract for classes to implement. They specify the methods and properties that
implementing classes must provide.
They support multiple inheritance of behavior and promote loose coupling between classes.
interface IShape
{
void Draw();
}
class Rectangle : IShape
{
public void Draw()
{
Console.WriteLine("Drawing a rectangle.");
}
}
Inheritance
Inheritance is a fundamental concept in object-oriented programming (OOP) that allows a class
(called a derived class or subclass) to inherit properties and behavior from another class (called a
base class or superclass). In C#, inheritance is implemented using the : symbol followed by the name
of the base class. Here's an overview of inheritance in C#:
// Base class
public class Animal
{
public void Eat()
{
Console.WriteLine("Animal is eating.");
}
}
// Derived class
public class Dog : Animal
{
public void Bark()
{
Console.WriteLine("Dog is barking.");
}
}
Syntax:
To declare a class as a derived class, use a colon (:) followed by the name of the base class.The
derived class inherits all non-private members (fields, properties, methods) of the base class.
public class DerivedClass : BaseClass
{
// Members of the derived class
}
Access Modifiers:
Inheritance respects access modifiers such as public, protected, internal, and private. Derived
classes can access public and protected members of the base class.
Constructor Inheritance:
Constructors are not inherited by derived classes, but the derived class must invoke a constructor of
the base class.
This can be done explicitly using the base keyword.
Method Overriding:
Derived classes can override base class methods by providing a new implementation. Use the
override keyword to indicate that a method overrides a base class method.
public class Dog : Animal
{
public override void Eat()
{
Console.WriteLine("Dog is eating.");
}
}
Sealed
In C#, the sealed modifier is used to prevent inheritance of a class or overriding of virtual methods.
When a class is marked as sealed, it cannot be used as a base class for further derivation. Similarly,
when a method is marked as sealed, it cannot be overridden in derived classes. Here's how sealed
works in C#:
Sealed Classes:
When a class is marked as sealed, it means that the class cannot be used as a base class for
inheritance. It prevents other classes from deriving from it.
public sealed class SealedClass
{
// Class members
}
Sealed Methods:
When a method in a base class is marked as sealed, it means that the method cannot be overridden
in derived classes.This is useful when you want to prevent further specialization of behavior defined
in the base class method.
public class BaseClass
{
public virtual void MyMethod()
{
// Method implementation
}
}
public class DerivedClass : BaseClass
{
public sealed override void MyMethod()
{
// Sealed method implementation
}
}
Usage:
The sealed modifier is used to restrict inheritance and overriding in scenarios where further derivation
or overriding is not desired.It can be applied to both classes and methods.
Benefits:
Helps in code optimization and performance improvements by preventing unnecessary virtual method
calls in the inheritance hierarchy.Enhances code security by restricting unintended derivation or
overriding of classes and methods.
Considerations:
Use sealed sparingly and only when necessary to prevent further derivation or overriding.Overuse of
sealed can limit the flexibility and extensibility of the codebase.
Static
In C#, the static keyword is used to define members (fields, methods, properties, constructors, and
nested types) that belong to the type itself rather than to instances of the type. Here's how static
works in various contexts:
Static Fields:
Static fields are shared across all instances of a class. They belong to the class rather than to any
specific instance.Static fields are initialized once when the class is loaded into memory and are
shared among all instances of the class.
public class MyClass
{
public static int StaticField = 10;
}
Static Methods:
Static methods belong to the class rather than to instances of the class. They can be called directly
on the class without creating an instance.Static methods cannot access instance members directly
but can access other static members.
public class MyClass
{
public static void StaticMethod()
{
Console.WriteLine("Static method called.");
}
}
Static Properties:
Static properties are similar to static fields but provide a getter and setter to access and modify the
underlying static field.
public class MyClass
{
private static int staticField;
Static Constructors:
Static constructors are called only once, when the class is first accessed or instantiated.
They are used to initialize static fields or perform any one-time initialization for the class.
Static Classes:
A static class is a class that only contains static members. It cannot be instantiated, and all its
members are accessed directly through the class name.
public static class UtilityClass
{
public static void DoSomething()
{
// Static method in a static class
}
}
UtilityClass.DoSomething(); // Calling static method from a static class
Static members are used when the behavior or data is shared across all instances of a class or when
the behavior does not depend on the state of any specific instance. They provide a way to organize
and access common functionality without requiring an instance of the class.
Abstract
In C#, the abstract keyword is used to define abstract classes and abstract members within those
classes. Abstract classes cannot be instantiated directly, and they may contain abstract methods that
must be implemented by non-abstract derived classes. Here's an overview of how abstract works:
Abstract Classes:
An abstract class is a class that cannot be instantiated directly. It serves as a base class for other
classes and may contain abstract and non-abstract members.
public abstract class Animal
{
public abstract void MakeSound(); // Abstract method
public void Eat() // Non-abstract method
{
Console.WriteLine("Animal is eating.");
}
}
Abstract Methods:
An abstract method is a method without a body, declared using the abstract keyword. It must be
implemented by non-abstract derived classes.
Abstract Properties:
Abstract properties are similar to abstract methods but represent properties instead. They do not
have an implementation and must be implemented by derived classes.
Derived Classes:
Derived classes from abstract classes must provide concrete implementations for all abstract
members declared in the base abstract class.
Instantiation:
Abstract classes cannot be instantiated directly. However, they can be used as a base for other
classes, which provide implementations for all abstract members.
Use Cases:
Abstract classes are useful when you want to define a common interface for a group of related
classes but don't want to provide a default implementation for some methods or properties.
They are also handy when you want to enforce certain behaviors to be implemented by derived
classes.
Starting from C# 8.0, interfaces can also contain abstract members. These members are implicitly
abstract and must be implemented by classes that implement the interface.
Abstract classes provide a way to define a common interface for a group of related classes while
allowing for flexibility in their implementation. They are essential for building hierarchies of classes
with shared behavior and contracts.
Interface - Concepts:
In C#, an interface is a reference type that defines a contract for classes to implement. It contains
only the declaration of methods, properties, events, or indexers but not their implementation. Here's
an overview of the key concepts related to interfaces in C#:
Interface Declaration:
An interface is declared using the interface keyword followed by the interface name and a list of
members.
Interface Members:
Interface members include methods, properties, events, and indexers.These members are implicitly
public and abstract, and they cannot contain any access modifiers.They define a contract that
implementing classes must adhere to.
Implementing Interfaces:
A class implements an interface by providing concrete implementations for all the members declared
in the interface.
A class can implement multiple interfaces by separating them with commas in the class declaration.
public class MyClass : IMyInterface1, IMyInterface2
{
// Implementations for interface members
}
Interface Inheritance:
Interfaces can inherit from one or more other interfaces using the : syntax.
ISP is a design principle that states that no client should be forced to depend on methods it
does not use.It suggests splitting large interfaces into smaller, more specific ones.
Use Cases:
Interfaces are commonly used to define contracts for classes that have similar behavior but
different implementations.They facilitate polymorphism and decoupling in software design by
allowing objects to be treated uniformly based on their interfaces.Interfaces are a powerful
tool in C# for designing flexible and extensible systems. They enable code reusability,
maintainability, and testability by promoting loose coupling between components.
Sunbeam Institute of Information Technology Pune and Karad
Delegates:
Delegates are a type-safe, object-oriented function pointers that allow methods to be passed as
parameters to other methods. They define the signature and return type of the method(s) they can
reference.
Declaration:
delegate returnType DelegateName(parameters);
Events:
Events are special types of delegates that encapsulate methods to be called when a certain
action or notification occurs. They are used to implement the publisher-subscriber pattern.
Declaration:
public event DelegateName EventName;
Basic Usage:
Define Delegate: Define a delegate that matches the signature of the methods you want to
encapsulate.
Raise Event: Call the event, which will execute all subscribed methods.
using System;
// Subscribe methods to
event
program.Subscribe(Metho
d1);
program.Subscribe(Metho
d2);
// Raise event
program.RaiseEvent("Event
triggered!");
Console.ReadLine();
}
mathematica
Events and delegates are extensively used in C# for implementing various patterns like
observer, command, etc., as well as in frameworks like Windows Forms and WPF for handling
UI events.
Sunbeam Institute of Information Technology Pune and Karad
File IO :
File handling is a very crucial and important feature for many enterprise applications around
us. To support this feature Microsoft .NET Framework offers the System.IO namespace, that provides
various classes to enable the developers to do I/O.
Objectives:
Using the File class for reading and writing data.
Using the File and FileInfo class to manipulate files.
Using the DirectoryInfo and Directory classes to manipulate directories.
The File class of the System.IO namespace offers various static methods that enable a developer to
do direct reading and writing of files. Typically, to read data from a file, you:
1. Get a hold on the file handle.
2. Open a stream to the file.
3. Buffer the file data into memory.
4. Release the hold of file handle once done.
The "ReadAllLines" method reads all the contents of a file and stores each line at a new index in an
array of string type.
The "ReadAllBytes" method reads the contents of a file as binary data and stores the data in a byte
array.
Each of these methods enable the developer to read the contents of a file and load into memory. The
ReadAllText method will enable the developer to cache the entire file in memory via a single
operation. Whereas the ReadAllLines method will read line-by-line into an array.
Writing Data to Files : data is written to a file. By default, all existing contents are removed
from the file, and new content is written.
Sunbeam Institute of Information Technology Pune and Karad
The "WriteAllText" method enables the developers to write the contents of string variable into a file. If
the file exists, its contents will be overwritten. The following code example shows how to write the
contents of a string named settings to a new file named settings.txt.
The "WriteAllLines" method enables the developers to write the contents of a string array to a file.
Each entry in the string array will be a new line in the new file.
Appending Data to Files – writing information to a file. The only difference is that the existing data in
a file is not overwritten. The new data to be written is added at the end of the file.
The "AppendAllText" method enables the developers to write the contents of a string variable at the
end of an existing file.
The "AppendAllLines" method enables the developers to write the contents of a string array to the
end of an existing file.
File IO Steps :
1. Creating a file :
We use theCreate() method of theFile class to create a new file in C#. For example,
Note: If the file already exists, the Create() method overwrites the file.
Example:
using System;
using System.IO;
class Program
{
static void Main()
{
// path of the file that we want to create
string pathName = @"C:\Program\myFile.txt";
2. Open a file :
We use the Open() method of the File class to open an existing file in C#. The method opens
aFileStream on the specified file.
Example:
using System;
using System.IO;
class Program
{
static void Main()
{
Sunbeam Institute of Information Technology Pune and Karad
Here, theOpen() method opensmyFile.txt file. Here,FileMode.Openspecifies -open the existing file.
3. Write to a file :
We use theWriteAllText() method of theFile class to write to a file. The method creates a new file and
writes content to that file
Example:
using System;
using System.IO;
class Program
{
static void Main()
{
string pathName = @"C:\Program\myFile.txt";
Here,the WriteAllText() method creates myFile.txt at c:\Program directory and writes “Hello Word” to
the file.
Sunbeam Institute of Information Technology Pune and Karad
4. Read a file :
We use theReadAllText() method of the File class to read contents of the file. The method
returns a string containing all the text in the specified file.
Let's read the content of the filemyFile.txt where we had written"Hello World".
Exam
ple:
using
Syste
m;
using
System.IO;
class
Program
{
static void Main()
{
string pathName = @"C:\Program\myFile.txt";
Console.WriteLine(readText);
}
}
The readAllText() method read the file myFile.txt and returns “Hello World”.
Serialization :
serialization is the process of converting object into byte stream so that it can be saved
to memory, file or database
Generics
Generics in C# allow you to write flexible and reusable code by creating classes, structures,
interfaces, and methods that can work with any data type. They provide type safety without
sacrificing flexibility. Here's an overview of how generics work:
Basic Syntax:
class ClassName<T>
{
// Members, methods, properties, etc.
}
T is a type parameter, representing any data type. You can use any valid identifier instead of T.
Example:
Usage:
Constraints:
You can apply constraints on generic type parameters to specify capabilities that generic types
must have. Common constraints include where T : class, where T : struct, where T : interface,
where T : new() (parameterless constructor), and custom constraints.
Example with Constraints:
public class MyClass<T> where T : IDisposable
{
// Methods can use IDisposable methods on T
}
Generics are extensively used in .NET framework collections (like List<T>), LINQ, and various
other scenarios where type safety and code reuse are essential. They help to avoid code
duplication and increase the flexibility and maintainability of your codebase.
Sunbeam Institute of Information Technology Pune and Karad
The following statement implicitly applies the boxing operation on the variable i:
int i = 123;
// The following line boxes i.
object o = i;
The result of this statement is creating an object reference o, on the stack, that references a value of the type
int, on the heap. This value is a copy of the value-type value assigned to the variable i. The difference between
the two variables, i and o, is illustrated in the following image of boxing conversion
It is also possible to perform the boxing explicitly as in the following example, but explicit boxing is never
required:
int i = 123;
object o = (object)i; // explicit boxing
Unboxing
Unboxing is an explicit conversion from the type object to a value type or from an interface type to a value
type that implements the interface. An unboxing operation consists of:
Checking the object instance to make sure that it is a boxed value of the given value type.
Copying the value from the instance into the value-type variable.
Arrays
You can store multiple variables of the same type in an array data structure. You declare an array by specifying
the type of its elements. If you want the array to store elements of any type, you can specify object as its type.
type[] arrayName;
// Set the values of the first array in the jagged array structure.
jaggedArray[0] = [1, 2, 3, 4];
Single-dimensional arrays
A single-dimensional array is a sequence of like elements. You access an element via its index. The index is its
ordinal position in the sequence. The first element in the array is at index 0. You create a single-dimensional
array using the new operator specifying the array element type and the number of elements.
The following example declares and initializes single-dimensional arrays:
Console.WriteLine(weekDays[0]);
Console.WriteLine(weekDays[1]);
Console.WriteLine(weekDays[2]);
Console.WriteLine(weekDays[3]);
Console.WriteLine(weekDays[4]);
Console.WriteLine(weekDays[5]);
Console.WriteLine(weekDays[6]);
/*Output:
Sun
Mon
Tue
Wed
Thu
Fri
Sat
*/
he first declaration declares an uninitialized array of five integers, from array[0] to array[4]. The elements of
the array are initialized to the default value of the element type, 0 for integers. The second declaration
declares an array of strings and initializes all seven values of that array. A series of Console.WriteLine
statements prints all the elements of the weekDay array.
Multidimensional arrays
Arrays can have more than one dimension. For example, the following declarations create four arrays: two
have two dimensions, two have three dimensions. The first two declarations declare the length of each
dimension, but don't initialize the values of the array. The second two declarations use an initializer to set the
values of each element in the multidimensional array.
Sunbeam Institute of Information Technology Pune and Karad
// Two-dimensional array.
int[,] array2DInitialization = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// Three-dimensional array.
int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
System.Console.WriteLine(array2DInitialization[3, 0]);
System.Console.WriteLine(array2DInitialization[3, 1]);
// Output:
// 1
// 2
// 3
// 4
// 7
// 8
System.Console.WriteLine(array3D[1, 0, 1]);
System.Console.WriteLine(array3D[1, 1, 2]);
// Output:
// 8
// 12
For multi-dimensional arrays, elements are traversed such that the indices of the rightmost dimension are
incremented first, then the next left dimension, and so on, to the leftmost index. The following example
enumerates both a 2D and a 3D array:
int[,] numbers2D = { { 9, 99 }, { 3, 33 }, { 5, 55 } };
In a 2D array, you can think of the left index as the row and the right index as the column.
However, with multidimensional arrays, using a nested for loop gives you more control over the order in
which to process the array elements:
Jagged arrays
A jagged array is an array whose elements are arrays, possibly of different sizes. A jagged array is sometimes
called an "array of arrays." Its elements are reference types and are initialized to null. The following examples
show how to declare, initialize, and access jagged arrays. The first example, jaggedArray, is declared in one
statement. Each contained array is created in subsequent statements. The second example, jaggedArray2 is
declared and initialized in one statement. It's possible to mix jagged and multidimensional arrays. The final
Sunbeam Institute of Information Technology Pune and Karad
example, jaggedArray3, is a declaration and initialization of a single-dimensional jagged array that contains
three two-dimensional array elements of different sizes.
int[][] jaggedArray2 =
[
[1, 3, 5, 7, 9],
[0, 2, 4, 6],
[11, 22]
];
int[][,] jaggedArray3 =
[
new int[,] { {1,3}, {5,7} },
new int[,] { {0,2}, {4,6}, {8,10} },
new int[,] { {11,22}, {99,88}, {0,9} }
];
A jagged array's elements must be initialized before you can use them. Each of the elements is itself an array.
It's also possible to use initializers to fill the array elements with values. When you use initializers, you don't
need the array size.
// Accessing array
Console.WriteLine("First element: " + a[0]);
Console.WriteLine("Second element: " + a[1]);
Console.WriteLine("Third element: " + a[2]);
Console.WriteLine("Fourth element: " + a[3]);
/* Outputs
First element: 1
Second element: 10
Third element: 100
Fourth element: 1000
*/
In the previous example, notice that with implicitly typed arrays, no square brackets are used on the left side
of the initialization statement. Also, jagged arrays are initialized by using new [] just like single-dimensional
arrays.
When you create an anonymous type that contains an array, the array must be implicitly typed in the type's
object initializer. In the following example, contacts is an implicitly typed array of anonymous types, each of
which contains an array named PhoneNumbers. The var keyword isn't used inside the object initializers.
All collections can be copied to an array using the CopyTo method. However, the order of the elements in the
new array is based on the sequence in which the enumerator returns them. The resulting array is always one-
dimensional with a lower bound of zero.
The capacity of a collection is the number of elements it can contain. The count of a collection is the number
of elements it actually contains. Some collections hide the capacity or the count or both.
Most collections automatically expand in capacity when the current capacity is reached. The memory is
reallocated, and the elements are copied from the old collection to the new one. This design reduces the code
required to use the collection. However, the performance of the collection might be negatively affected. For
example, for List, if Count is less than Capacity, adding an item is an O(1) operation. If the capacity needs to
be increased to accommodate the new element, adding an item becomes an O(n) operation, where n is
Count. The best way to avoid poor performance caused by multiple reallocations is to set the initial capacity
to be the estimated size of the collection.
A BitArray is a special case; its capacity is the same as its length, which is the same as its count.
The lower bound of a collection is the index of its first element. All indexed collections in the
System.Collections namespaces have a lower bound of zero, meaning they're 0-indexed. Array has a lower
bound of zero by default, but a different lower bound can be defined when creating an instance of the Array
class using Array.CreateInstance.
Non-generic collection types in the System.Collections namespace provide some thread safety with
synchronization; typically exposed through the SyncRoot and IsSynchronized members. These collections
aren't thread-safe by default. If you require scalable and efficient multi-threaded access to a collection, use
one of the classes in the System.Collections.Concurrent namespace or consider using an immutable collection.
For more information, see Thread-Safe Collections.
Choose a collection
In general, you should use generic collections. The following table describes some common collection
scenarios and the collection classes you can use for those scenarios. If you're new to generic collections, the
following table will help you choose the generic collection that works best for your task:
ArrayList
Sunbeam Institute of Information Technology Pune and Karad
Definition
Namespace: System.Collections
Assembly: System.Runtime.dll
Implements the IList interface using an array whose size is dynamically increased as required.
Examples
The following example shows how to create and initialize an ArrayList and how to display its values.
using System;
using System.Collections;
public class SamplesArrayList {
/*
This code produces output similar to the following:
myAL
Count: 3
Capacity: 4
Values: Hello World !
*/
Remarks
The ArrayList is not guaranteed to be sorted. You must sort the ArrayList by calling its Sort method prior to
performing operations (such as BinarySearch) that require the ArrayList to be sorted. To maintain a collection
that is automatically sorted as new elements are added, you can use the SortedSet class.
The capacity of an ArrayList is the number of elements the ArrayList can hold. As elements are added to an
ArrayList, the capacity is automatically increased as required through reallocation. The capacity can be
decreased by calling TrimToSize or by setting the Capacity property explicitly.
.NET Framework only: For very large ArrayList objects, you can increase the maximum capacity to 2 billion
elements on a 64-bit system by setting the enabled attribute of the configuration element to true in the run-
time environment.
Elements in this collection can be accessed using an integer index. Indexes in this collection are zero-based.
The ArrayList collection accepts null as a valid value. It also allows duplicate elements.
Constructors
Properties
Methods
Hashtable
Sunbeam Institute of Information Technology Pune and Karad
Namespace: System.Collections
Assembly: System.Runtime.dll
Represents a collection of key/value pairs that are organized based on the hash code of the key.
The following example shows how to create, initialize and perform various functions to a Hashtable and how
to print out its keys and values.
using System;
using System.Collections;
class Example
{
public static void Main()
{
// Create a new hash table.
//
Hashtable openWith = new Hashtable();
if (!openWith.ContainsKey("doc"))
{
Console.WriteLine("Key \"doc\" is not found.");
}
}
}
Value = paint.exe
Value = notepad.exe
Value = hypertrm.exe
Value = paint.exe
Value = winword.exe
Value = winword.exe
Key = dib
Key = txt
Key = ht
Key = bmp
Key = rtf
Key = doc
Remove("doc")
Key "doc" is not found.
*/
Each element is a key/value pair stored in a DictionaryEntry object. A key cannot be null, but a value can
be.
The objects used as keys by a Hashtable are required to override the Object.GetHashCode method (or
the IHashCodeProvider interface) and the Object.Equals method (or the IComparer interface). The
implementation of both methods and interfaces must handle case sensitivity the same way; otherwise,
the Hashtable might behave incorrectly. For example, when creating a Hashtable, you must use the
CaseInsensitiveHashCodeProvider class (or any case-insensitive IHashCodeProvider implementation)
with the CaseInsensitiveComparer class (or any case-insensitive IComparer implementation).
Furthermore, these methods must produce the same results when called with the same parameters
while the key exists in the Hashtable. An alternative is to use a Hashtable constructor with an
IEqualityComparer parameter. If key equality were simply reference equality, the inherited
implementation of Object.GetHashCode and Object.Equals would suffice.
Sunbeam Information Technology,Pune and Karad
Key objects must be immutable as long as they are used as keys in the Hashtable.
When an element is added to the Hashtable, the element is placed into a bucket based on the hash
code of the key. Subsequent lookups of the key use the hash code of the key to search in only one
particular bucket, thus substantially reducing the number of key comparisons required to find an
element.
The load factor of a Hashtable determines the maximum ratio of elements to buckets. Smaller load
factors cause faster average lookup times at the cost of increased memory consumption. The default
load factor of 1.0 generally provides the best balance between speed and size. A different load factor
can also be specified when the Hashtable is created.
As elements are added to a Hashtable, the actual load factor of the Hashtable increases. When the
actual load factor reaches the specified load factor, the number of buckets in the Hashtable is
automatically increased to the smallest prime number that is larger than twice the current number of
Hashtable buckets.
Each key object in the Hashtable must provide its own hash function, which can be accessed by calling
GetHash. However, any object implementing IHashCodeProvider can be passed to a Hashtable
constructor, and that hash function is used for all objects in the table.
The capacity of a Hashtable is the number of elements the Hashtable can hold. As elements are added
to a Hashtable, the capacity is automatically increased as required through reallocation.
.NET Framework only: For very large Hashtable objects, you can increase the maximum capacity to 2
billion elements on a 64-bit system by setting the enabled attribute of the configuration element to
true in the run-time environment.
The foreach statement of the C# language (For Each in Visual Basic) returns an object of the type of the
elements in the collection. Since each element of the Hashtable is a key/value pair, the element type is
not the type of the key or the type of the value. Instead, the element type is DictionaryEntry.
foreach(DictionaryEntry de in myHashtable)
{
// ...
}
The foreach statement is a wrapper around the enumerator, which only allows reading from, not writing
to, the collection.
Because serializing and deserializing an enumerator for a Hashtable can cause the elements to become
reordered, it is not possible to continue enumeration without calling the Reset method.
Constructors
Sunbeam Information Technology,Pune and Karad
Sunbeam Information Technology,Pune and Karad
Properties
Methods
Sunbeam Information Technology,Pune and Karad
Thread Safety
Sunbeam Information Technology,Pune and Karad
Hashtable is thread safe for use by multiple reader threads and a single writing thread. It is thread safe for
multi-thread use when only one of the threads perform write (update) operations, which allows for lock-free
reads provided that the writers are serialized to the Hashtable. To support multiple writers all operations on
the Hashtable must be done through the wrapper returned by the Synchronized(Hashtable) method, provided
that there are no threads reading the Hashtable object.
Generic Collections
Namespace: System.Collections.Generic
Contains interfaces and classes that define generic collections, which allow users to create strongly
typed collections that provide better type safety and performance than non-generic strongly typed
collections.
Classes
Sunbeam Information Technology,Pune and Karad
Sunbeam Information Technology,Pune and Karad
Structs
Sunbeam Information Technology,Pune and Karad
Interfaces
Sunbeam Information Technology,Pune and Karad
Many of the generic collection types are direct analogs of nongeneric types. Dictionary<TKey,TValue> is
a generic version of Hashtable; it uses the generic structure KeyValuePair<TKey,TValue> for
enumeration instead of DictionaryEntry. List is a generic version of ArrayList. There are generic Queue
and Stack classes that correspond to the nongeneric versions. There are generic and nongeneric
versions of SortedList<TKey,TValue>. Both versions are hybrids of a dictionary and a list. The
SortedDictionary<TKey,TValue> generic class is a pure dictionary and has no nongeneric counterpart.
The LinkedList generic class is a true linked list and has no nongeneric counterpart.
List Class
Namespace: System.Collections.Generic
Assembly: System.Collections.dll
Represents a strongly typed list of objects that can be accessed by index. Provides methods to search, sort,
and manipulate lists.
Type Parameters
Characteristics:
It is different from the arrays. A List can be resized dynamically but arrays cannot.
List class can accept null as a valid value for reference types and it also allows duplicate elements.
If the Count becomes equals to Capacity, then the capacity of the List increased automatically by
reallocating the internal array. The existing elements will be copied to the new array before the addition
of the new element.
List class is the generic equivalent of ArrayList class by implementing the IList generic interface.
This class can use both equality and ordering comparer.
List class is not sorted by default and elements are accessed by zero-based index.
For very large List objects, you can increase the maximum capacity to 2 billion elements on a 64-bit
system by setting the enabled attribute of the configuration element to true in the run-time
environment.
Constructors
Example
Properties
Methods
Sunbeam Information Technology,Pune and Karad
Sunbeam Information Technology,Pune and Karad
Sunbeam Information Technology,Pune and Karad
Example
Sunbeam Information Technology,Pune and Karad
class Demo {
// Main Method
public static void Main(String[] args)
{
int p = 0;
Console.WriteLine(" ");
int p1 = 0;
}
}
}
/*
Elements Present in List:
At Position 0: 17
At Position 1: 19
At Position 2: 21
At Position 3: 9
At Position 4: 75
At Position 5: 19
At Position 6: 73
At Position 0: 17
At Position 1: 19
At Position 2: 21
At Position 3: 75
At Position 4: 19
At Position 5: 73
*/
Reference
Stack class
Stack represents a last-in, first out collection of object. It is used when you need a last-in, first-out
access to items. When you add an item in the list, it is called pushing the item and when you remove it,
it is called popping the item. This class comes under System.Collections.Generic namespace.
The capacity of a Stack is the number of elements the Stack can hold. As elements are added to a Stack,
the capacity is automatically increased as required by reallocating the internal array. The capacity can
be decreased by calling TrimExcess.
Stack accepts null as a valid value for reference types and allows duplicate elements.
The following example shows how to create and add values to a Stack and how to display its values.
using System;
using System.Collections.Generic;
class Example
{
public static void Main()
{
Stack<string> numbers = new Stack<string>();
numbers.Push("one");
numbers.Push("two");
numbers.Push("three");
numbers.Push("four");
numbers.Push("five");
// Create a copy of the stack, using the ToArray method and the
// constructor that accepts an IEnumerable<T>.
Stack<string> stack2 = new Stack<string>(numbers.ToArray());
// Create an array twice the size of the stack and copy the
// elements of the stack, starting at the middle of the
// array.
string[] array2 = new string[numbers.Count * 2];
numbers.CopyTo(array2, numbers.Count);
nulls:");
foreach( string number in stack3 )
{
Console.WriteLine(number);
}
Console.WriteLine("\nstack2.Contains(\"four\") = {0}",
stack2.Contains("four"));
Console.WriteLine("\nstack2.Clear()");
stack2.Clear();
Console.WriteLine("\nstack2.Count = {0}", stack2.Count);
}
}
five
four
three
two
one
Popping 'five'
Peek at next item to destack: four
Popping 'four'
stack2.Contains("four") = False
stack2.Clear()
stack2.Count = 0
*/
Constructors
Sunbeam Information Technology,Pune and Karad
Properties
Methods
Sunbeam Information Technology,Pune and Karad
Reference
Oueue class
Namespace: System.Collections.Generic Inheritance: Object -> Queue Implements: IEnumerable
IReadOnlyCollection ICollection IEnumerable
This class implements a generic queue as a circular array. Objects stored in a Queue are inserted at one
end and removed from the other. Queues and stacks are useful when you need temporary storage for
information; that is, when you might want to discard an element after retrieving its value. Use Queue if
you need to access the information in the same order that it is stored in the collection. Use Stack if you
need to access the information in reverse order. Use ConcurrentQueue or ConcurrentStack if you need
to access the collection from multiple threads concurrently.
Three main operations can be performed on a Queue and its elements: - Enqueue adds an element to
the end of the Queue. - Dequeue removes the oldest element from the start of the Queue. - Peek peek
Sunbeam Information Technology,Pune and Karad
returns the oldest element that is at the start of the Queue but does not remove it from the Queue.
The capacity of a Queue is the number of elements the Queue can hold. As elements are added to a
Queue, the capacity is automatically increased as required by reallocating the internal array. The
capacity can be decreased by calling TrimExcess.
Queue accepts null as a valid value for reference types and allows duplicate elements.
Examples
The following code example demonstrates several methods of the Queue generic class. The code example
creates a queue of strings with default capacity and uses the Enqueue method to queue five strings. The
elements of the queue are enumerated, which does not change the state of the queue. The Dequeue method
is used to dequeue the first string. The Peek method is used to look at the next item in the queue, and then
the Dequeue method is used to dequeue it.
The ToArray method is used to create an array and copy the queue elements to it, then the array is passed to
the Queue constructor that takes IEnumerable, creating a copy of the queue. The elements of the copy are
displayed.
An array twice the size of the queue is created, and the CopyTo method is used to copy the array elements
beginning at the middle of the array. The Queue constructor is used again to create a second copy of the
queue containing three null elements at the beginning.
The Contains method is used to show that the string "four" is in the first copy of the queue, after which the
Clear method clears the copy and the Count property shows that the queue is empty.
using System;
using System.Collections.Generic;
class Example
{
public static void Main()
{
Queue<string> numbers = new Queue<string>();
numbers.Enqueue("one");
numbers.Enqueue("two");
numbers.Enqueue("three");
numbers.Enqueue("four");
numbers.Enqueue("five");
// Create a copy of the queue, using the ToArray method and the
// constructor that accepts an IEnumerable<T>.
Queue<string> queueCopy = new Queue<string>(numbers.ToArray());
// Create an array twice the size of the queue and copy the
// elements of the queue, starting at the middle of the
// array.
string[] array2 = new string[numbers.Count * 2];
numbers.CopyTo(array2, numbers.Count);
Console.WriteLine("\nqueueCopy.Contains(\"four\") = {0}",
queueCopy.Contains("four"));
Console.WriteLine("\nqueueCopy.Clear()");
queueCopy.Clear();
Console.WriteLine("\nqueueCopy.Count = {0}", queueCopy.Count);
}
}
one
two
three
four
five
Dequeuing 'one'
Peek at next item to dequeue: two
Dequeuing 'two'
Constructor
Properties
Methods
Sunbeam Information Technology,Pune and Karad
Dictionary class
In C#, Dictionary is a generic collection which is generally used to store key/value pairs. The working of
Dictionary is quite similar to the non-generic hashtable. The advantage of Dictionary is, it is generic
type. Dictionary is defined under System.Collections.Generic namespace. It is dynamic in nature means
the size of the dictionary is grows according to the need.
Sunbeam Information Technology,Pune and Karad
Important Points:
Examples
The following code example creates an empty Dictionary<TKey,TValue> of strings with string keys and uses
the Add method to add some elements. The example demonstrates that the Add method throws an
ArgumentException when attempting to add a duplicate key.
The example uses the Item[] property (the indexer in C#) to retrieve values, demonstrating that a
KeyNotFoundException is thrown when a requested key is not present, and showing that the value associated
with a key can be replaced.
The example shows how to use the TryGetValue method as a more efficient way to retrieve values if a program
often must try key values that are not in the dictionary, and it shows how to use the ContainsKey method to
test whether a key exists before calling the Add method.
The example shows how to enumerate the keys and values in the dictionary and how to enumerate the keys
and values alone using the Keys property and the Values property.
// If a key does not exist, setting the indexer for that key
// adds a new key/value pair.
openWith["doc"] = "winword.exe";
// When a program often has to try keys that turn out not to
// be in the dictionary, TryGetValue can be a more efficient
// way to retrieve values.
string value = "";
if (openWith.TryGetValue("tif", out value))
{
Console.WriteLine("For key = \"tif\", value = {0}.", value);
}
else
{
Console.WriteLine("Key = \"tif\" is not found.");
}
Console.WriteLine();
foreach( KeyValuePair<string, string> kvp in openWith )
{
Console.WriteLine("Key = {0}, Value = {1}",
kvp.Key, kvp.Value);
}
if (!openWith.ContainsKey("doc"))
{
Console.WriteLine("Key \"doc\" is not found.");
}
Value = notepad.exe
Value = paint.exe
Value = paint.exe
Value = winword.exe
Value = winword.exe
Value = hypertrm.exe
Key = txt
Key = bmp
Key = dib
Key = rtf
Key = doc
Key = ht
Remove("doc")
Key "doc" is not found.
*/
Remnarks
The Dictionary<TKey,TValue> generic class provides a mapping from a set of keys to a set of values.
Each addition to the dictionary consists of a value and its associated key. Retrieving a value by using its
key is very fast, close to O(1), because the Dictionary<TKey,TValue> class is implemented as a hash
table.
As long as an object is used as a key in the Dictionary<TKey,TValue>, it must not change in any way
that affects its hash value. Every key in a Dictionary<TKey,TValue> must be unique according to the
dictionary's equality comparer. A key cannot be null, but a value can be, if its type TValue is a reference
type.
.NET Framework only: For very large Dictionary<TKey,TValue> objects, you can increase the maximum
capacity to 2 billion elements on a 64-bit system by setting the enabled attribute of the configuration
element to true in the run-time environment.
Constructor
Sunbeam Information Technology,Pune and Karad
Properties
Sunbeam Information Technology,Pune and Karad
Methods
Sunbeam Information Technology,Pune and Karad
Sunbeam Information Technology,Pune and Karad
Reflection :
Reflection Attributes :
Attributes provide a powerful method of associating metadata, or declarative information, with code
(assemblies, types, methods, properties, and so forth). After an attribute is associated with a program
entity, the attribute can be queried at run time by using a technique called reflection.
Finally, the class YourClass is inherited from the base class MyClass. The
method MyMethod shows MyAttribute but not YourAttribute
3. Declaring constructors :
public MyAttribute(bool myvalue)
{
this.myvalue = myvalue;
}
4. Declaring properties :
public bool MyProperty
{
get {return
this.myvalue;} set
{this.myvalue =
value;}
}
The act of loading external assemblies on demand is known as Dynamic Loading. Using the
Assembly class, we can dynamically load both private and shared assemblies from the local
location to a remote location as well as, explore its properties.
Step 3 : Sign the component with the key and build the class
library project (Go to properties of the project in solution
explorer -> select signing -> Check the checkbox of Sign the
assembly and browse for the key).
ADO. NET consists of managed classes that allow .NET applications to Connect to data
sources (usually relational databases),execute commands, and manage disconnected data.
Connected Architecture
Connection:
Manages the connection to the database. In the case of Connection-Oriented Data Access
Architecture, an open and active connection is always required between the .NET Application
and the database.when we access data from the database, the Data Reader object requires
an active and open connection to access the data. If the connection is closed, we cannot
access the data from the database; in that case, we will get the runtime error.
Command:
Executes SQL queries, stored procedures, or commands on the database.The second
important component is the command object. When we discuss databases such as SQL
Server, Oracle, MySQL, then speak SQL, it is the command object that we use to create SQL
queries. After you create your SQL queries, you can execute them over the connection using
the command object.
DataReader:
Reads data from the database in a forward-only, read-only manner.The ADO.NET DataReader
object reads the data from the database using Connected Oriented Architecture.It requires an
active and open connection while reading the data from the database.
.NET Application
(Windows,Console,Web, DataBase
Restful etc)
Connection Oriented Data Ac cess Architecture
Select Query
string connectionDetails = @"Data Source=(LocalDB)\MSSQLLocalDB;Initial
Catalog=kdac;Integrated Security=True";
SqlConnection connection =
new SqlConnection(connectionDetails);
connection.Open();
SqlCommand command =
new SqlCommand("select * from Emp", connection);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Emp emp = new Emp();
emp.No = Convert.ToInt32(reader["No"]);
emp.Name = reader["Name"].ToString();
emp.Address = reader["address"].ToString();
emps.Add(emp);
}
connection.Close();
1. SqlConnection:
This is a class provided by the .NET framework for working with SQL Server
databases. It represents a connection to a SQL Server database. This class is part of
the System.Data.SqlClient namespace.
2. connection: This is the variable name that hold the `SqlConnection` object.
1. SqlCommand command :
This line declares a variable named `command` of type `SqlCommand`.
`SqlCommand` is a class provided by the ADO.NET framework, which is used to
execute SQL commands against a database.
a. select * from Emp - This is the SQL command that you want to
execute.select statement that retrives all columns from a table.
b. connection – This is an instance of a `SqlConnection` class. It
represents the connection to the database where you want to
execute the SQL command.
1. SqlDataReader reader:
This line declares a variable named `reader` of type `SqlDataReader`. `
SqlDataReader ` is a class provided by the ADO.NET for reading a forward-only
streams of rows from database.
2. command.ExecuteReader():
This method is used to execute the SQL command represented by the command
object and retrieve the resulting data as a data reader. When you call
`ExecuteReader()`, it sends the SQL command to the database server for execution.
DisConnected Architecture
DataAdapter: This object performs two tasks. First, you can use it to fill a
DataSet (a disconnected collection of tables and relationships) with information
extracted from a data source. Second, you can use it to apply changes to a
datasource, according to the modifications you’ve made in a DataSet. The
ADO.NET DataAdapter object acts as an interface between the .NET
application and the database.
DataSet: A DataSet is made up of a collection of tables, relationships, and
constraints. In ADO.NET, DataTable objects are used to represent the tables in
a DataSet.
The ADO.NET DataSet is a memory-resident representation of data that
provides a consistent relational programming model regardless of the source of
the data it contains. A DataSet represents a complete set of data including the
tables that contain, order, and constrain the data, as well as the relationships
between the tables.
Creating a DataSet:
You can create an instance of a DataSet by calling the DataSet
constructor. Optionally specify a name argument. If you do not specify a name
for the DataSet, the name is set to "NewDataSet". You can also create a
new DataSet based on an existing DataSet.
The new DataSet can be an exact copy of the existing DataSet, a clone of
the DataSet that copies the relational structure or schema but that does not
contain any of the data from the existing DataSet; or a subset of the DataSet,
containing only the modified rows from the existing DataSet using the
GetChanges method.
Data Table:
Creating a DataTable:
When you first create a DataTable, it does not have a schema (that is, a
structure). To define the schema of the table, you must create and add objects
to the Columns collection of the table. You can also define a primary key
column for the table, and create and add Constraint objects to the
Constraints collection of the table. After you have defined the schema for a
DataTable, you can add rows of data to the table by
adding DataRow objects to the Rows collection of the table.
.NET Application
(Windows,Web,Console, Data Adapter DataBase
Restful etc)
Data Transfer Objects (DTO) are used to transfer data between the
Application Layer and the Presentation Layer or other type of clients.
A DTO is nothing more than a container class that exposes properties but no
methods. A data transfer object (DTO) holds all data that is required for the
remote call. Your remote method will accept the DTO as a parameter and
return a DTO to the client.
Why Use DTOs?
Client
Request Operation Response Operation
Server
Creating and Using DTOs:
Step 1: Define the DTO class
FirstName LastName
new Employee { = 2, = "raj", = "Sutar",
Department = "HR" },
LastName
new Employee { EmployeeId = 3, FirstName = "Bhaiya", =
"Magdum", Department = "Finance" },
};
public EmployeeDTO GetEmployeeById(int employeeId)
{
var employee = _employees.FirstOrDefault(e => e.EmployeeId == employeeId);
if(employee == null)
{
return null;
}
return EmployeeMapper.MapToDTO(employee);
}
}
In this EmployeeService, we have a method GetEmployeeById that
retrieves an employee by their ID and maps the retrieved Employee object
to an EmployeeDTO using the EmployeeMapper class
Entity Framework:-
Writing POCO-:
POCO stands for "Plain Old CLR Object," and in the context of Entity
Framework, POCO classes are simple, non-framework-specific
classes that do not depend on any Entity Framework types.
These classes are used to represent entities in the domain model,
and they can be used with Entity Framework for data access without
requiring any dependencies on the framework itself.
POCO classes are often used to create a more maintainable and
testable domain model, as they are not tied to a specific data access
technology.
Using Attributes-:
Attributes are like adjectives, which are used for metadata annotation that can be applied to
a given type, assembly, module, method and so on. The .NET framework stipulates two
types of attribute implementations, which are Predefined Attributes and Custom Attributes.
Attributes are types derived from the System.Attribute class. This is an abstract class
defining the required services of any attribute. The following is the syntax of an attribute;
[type: attributeName(parameter1,parameter2, ------- n)]
Role Of Attributes-
Attributes might be useful for documentation purposes. They fulfill many roles, including
describing serialization, indicating conditional compilation, specifying import linkage and
setting class blueprint and so on. Attributes allow information to be defined and applied to
nearly any metadata table entry.
Prefined Attributes-
The System.Attribute base class library provides a number of attributes in various
namespaces. The following table gives a snapshot of some predefined attributes.
Attributes Description
[Serialization] By marking this attributes, a class is able to persist its current state
into stream.
Sunbeam Institute of Information Technology Pune and Karad
[NonSerialization] It specify that a given class or field should not persisted during the
serialization process.
Here, assume that you have developed a Test class that can be persisted in a binary format
using the [Serialization] attribute.
[Serializable]
public class test
{
public Test() { }
string name;
string country;
[NonSerialized]
int salary;
}
1. Table Attribute-
The Table attribute is applied to an entity to specify the name of the database table that the
entity should map to. The following example specifies that the Book entity should map to a
database table named tbl_Book:
[Table(“tbl_book”)]
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public Author Author { get; set; }
2. Column Attribute-
The Column attribute is applied to a property to specify the database column that the
property should map to when the entity's property name and the database column name
differ. The following example maps the Title property in the Book entity to a database column
named Description:
3. ForeignKey-
The ForeignKey attribute is used to specify which property is the foreign key in a
relationship.
public class Author
{
public int AuthorId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[ForeignKey(“AuthorFK”)]
public Icollection<Book> Books { get; set ; }
}
4. DatabaseGenerated-
The DatabaseGenerated attribute specifies how values are generated for a property by the
database. The attribute takes a DatabaseGeneratedOption enumeration value.
Computed-
The Computed option specifies that the property's value will be generated by the
database when the value is first saved, and subsequently regenerated every time the value
is updated.
Identity-
The Identity option specifies that the value will only be generated by the database
when a value is first added to the database.
Database providers differ in the way that values are automatically generated. Some
will generate values for selected data types such as Identity,rowversion.
}
Entity Framework Packages-:
Database providers:
EF Core supports different database systems through the use of “database providers
”. Each system has its own database provider,which is shipped as NuGet package.
Applications should install one or more of these provider packages.
Common database providers are listed in the table below.
PostgreSQL Npgsql.EntityFrameworkCore.PostgreSQL
MySQL EntityFrameworkCore.MySql
Commands-:
The command-line interface tools for Entity Framework core perform design-time
development tasks. For Example they create migrations,apply migrations and
generate code for a model based on an existing database. The commands are an
extension to the cross-platform dotnet command, which is part of the .NET Core
SDK.
When using Visual Studio,consider using the Package Manager Console tools
instead of the CLI tools. Package Manager Console tools automatically.
Works with the current project selected in the Package Manager Console
without requiring that you manually switch directories.
Opens files generated by a command after the command is completed.
Provides tab completion of commands,parameters,project names,context
types and migration names.
Argument Description
The target migration. Migrations may be
<MIGRATION> identified by name or by ID. The number 0 is
a special case that means before the first
migration and causes all migrations to be
reverted.
Removes the last migration, rolling back the code changes that were done for
the latest migration.
--force Revert the latest migration, rolling back both code and database
changes that were done for the latest migration.
Different Approaches
The Entity Framework provides three approaches to create an entity
model and each one has their own pros and cons.
• Code First
• Database First
• Model First
General overview of how you can use the Model First approach with
relations in Entity Framework:
2. Configure Relationship:
o In the conceptual model, you can define relationships
between entities. These relationships can be one-to-one,
one-to-many, or many-to-many.
o Configure the cardinality and navigation properties for
each relationship. For example, if you have a one-to-
many relationship between Department and Employee,
you would specify a collection navigation property in the
Department entity to represent the employees associated with that
department.
Partial Class
Anonymous Methods
Nullable Type
Iterator
Implicit Type
Auto Property
Object Initializer
Anonymous Type
Extension Methods
Lambda Expression
LINQ
Partial Methods
Dynamic Type
Optional | Named Parameters
Async | Await
Partial Class
In C#, a partial class is a class that can be split into multiple files. Each part of the partial class is
declared with the partial keyword. When compiled, all the parts are combined into a single class
definition.
Partial classes are often used in large projects or codebases to organize code more effectively,
especially when multiple developers are working on different parts of the same class or when a class
contains a significant amount of code. Here are some key points about partial classes:
1. Syntax: To declare a partial class, you use the partial keyword followed by the class keyword.
For example.
public partial class MyClass
{
// Class members and methods
}
2. Multiple Files: Each part of the partial class can be defined in a separate file within the same
namespace. All parts of the partial class must have the same access level modifier (public,
internal, etc.) and be declared within the same assembly.
3. Method Definitions: Partial methods are a special feature of partial classes. A partial method
is a method declaration without an implementation. One part of the partial class may declare a
partial method, and another part may provide the implementation. If the implementation is not
provided, the compiler removes the method call at compile time.
public partial class MyClass
{
partial void MyMethod();
}
// In another file:
public partial class MyClass
{
partial void MyMethod()
{
// Method implementation
}
}
4. Benefits: Partial classes can improve code organization, readability, and maintainability by
allowing developers to focus on specific parts of a class without cluttering a single file with a
large amount of code.
5. Usage: Partial classes are commonly used in GUI applications generated by visual designers
(e.g., Windows Forms, WPF) to separate auto-generated code from developer-written code.
They are also useful in frameworks and libraries where code generation or extension points
are involved.
Anonymous Methods
Anonymous methods in C# allow you to define a method inline without specifying a name. They are
particularly useful for defining event handlers or delegates where a simple, short method is required
and defining a separate named method would be overkill. Here are some key points about
anonymous methods:
1. Syntax: Anonymous methods are defined using the delegate keyword followed by a
parameter list (if any) and a code block enclosed in curly braces. For example:
delegate(int x, int y)
{
return x + y;
};
2. Usage with Delegates: Anonymous methods are often used in conjunction with delegates.
Instead of defining a separate named method and then passing it to a delegate, you can
define the method inline where it's needed.
For example:
printMessage("Hello, world!");
3. Capture of Outer Variables: Anonymous methods can capture variables from the outer
scope. This means they can access variables defined outside of their own scope. However,
they can only capture variables by reference, not by value. This can lead to unexpected
behavior if the outer variables are modified after the anonymous method is created.
Anonymous methods provide a convenient way to define short, inline functions without the need for a
separate named method. While they have largely been superseded by lambda expressions in
modern C# code, they are still occasionally used in scenarios where lambda expressions are not
applicable or where they would make the code less readable.
Nullable Type
In C#, a nullable type allows you to represent both a value type (like int, float, etc.) and the absence
of a value (null). This is particularly useful when dealing with database fields or other scenarios where
a value may or may not be present. Nullable types were introduced in C# 2.0.
The syntax for defining a nullable type is to append a question mark ? to the type declaration. For
example.
int? nullableInt;
float? nullableFloat;
Here are some key points about nullable types:
1. Value or Null: Nullable types allow a variable to hold either the underlying value type or a null
reference. For example, int? can hold any integer value or be null.
2. Nullable<T>: Behind the scenes, nullable types are implemented using the Nullable<T> struct
(also written as T?). This struct has two properties: HasValue which indicates whether the
nullable type has a value, and Value which returns the underlying value if HasValue is true, or
throws an exception if HasValue is false.
Iterator
In C#, an iterator is a block of code that enables you to iterate over a collection of items sequentially.
It simplifies the process of iterating over collections like arrays, lists, or custom data structures by
abstracting away the underlying implementation details of iteration. Iterators are commonly used with
foreach loops.
Here's how iterators work in C#:
1. Iterator Method: To create an iterator, you define a method that returns an IEnumerable<T>
or IEnumerator<T> object. This method uses the yield keyword to return each element of the
collection one at a time.
2. Yield Keyword: The yield keyword is used within the iterator method to return each element
of the collection. When the iterator method is called, execution starts from the beginning of the
method until the first yield statement is reached. The method then returns the value specified
by yield and suspends its execution. When the iterator is iterated again, execution resumes
from where it left off until the next yield statement is encountered, and so on.
Implicit Type
Implicit typing in C# allows you to declare variables without explicitly specifying their data types.
Instead, the compiler infers the data type based on the value assigned to the variable. This feature
was introduced in C# 3.0 with the var keyword.
1. Syntax: Instead of explicitly specifying the data type, you use the var keyword followed by
the variable name and an optional initializer. For example:
2. Type Inference: When the compiler encounters a variable declared with var, it analyzes the
expression on the right-hand side of the assignment operator (=) to determine its data type.
The compiler then assigns the inferred type to the variable.
3. Compile-Time Checking: Although the type of the variable is not explicitly specified, the
compiler performs type checking at compile time to ensure type safety. This means that the
variable's type is determined at compile time, and the compiler enforces type rules
accordingly.
4. Static Typing: Implicit typing does not change the statically-typed nature of C#. Once a
variable's type is inferred, it cannot be changed. The variable is still statically typed, meaning
its type is determined at compile time and cannot change during runtime.
5. Readability: Implicit typing can improve code readability by reducing verbosity, especially
when variable names are descriptive and the inferred types are obvious from the assigned
values.
6. Limitations: Implicit typing cannot be used in certain scenarios, such as when declaring
fields, method parameters, or return types, where the data type must be explicitly specified.
Additionally, using var with complex types or when the inferred type is not immediately
obvious can reduce code clarity.
Here's an example illustrating the usage of implicit typing:
class Program
{
static void Main()
{
var number = 10;
var message = "Hello, world!";
Auto Property
1. Syntax: Instead of explicitly declaring a backing field and writing separate getter and setter
methods, you can use a simplified syntax to define the property directly within the class. The
compiler automatically generates a private backing field for the property.
2. Access Modifiers: You can specify access modifiers (public, private, protected, etc.) for auto-
implemented properties just like regular properties. By default, auto-implemented properties
are public.
3. Initialization: You can provide an initial value for an auto-implemented property directly within
the property declaration.
public class MyClass
{
public int MyProperty { get; set; } = 42;
}
4. Read-Only Auto Properties: You can create read-only auto-implemented properties by
omitting the setter. In this case, the property can only be assigned a value within the
constructor or initializer.
public class MyClass
{
public int MyReadOnlyProperty { get; } = 42;
}
5. Backing Field: While auto-implemented properties do have a backing field generated by the
compiler, you cannot directly access this field from within the class. It's purely an
implementation detail.
Auto-implemented properties offer a concise and readable way to define properties in C#, especially
for simple scenarios where custom getter/setter logic is not required. However, they are limited in
flexibility compared to traditional properties, as you cannot directly manipulate the backing f ield or
provide custom logic within the getter/setter methods.
Object Initializer
In C#, object initializers provide a concise syntax for initializing objects without explicitly invoking a
constructor and setting individual properties one by one. This feature was introduced in C# 3.0 as
part of the language enhancements.
1. Syntax: Instead of using a constructor followed by property assignments, you can use the
object initializer syntax to set properties directly within curly braces { } after the object creation
expression.
2. Multiple Properties: You can initialize multiple properties within the same object initializer
block, separated by commas.
3. Nested Object Initializers: Object initializers can be nested to initialize properties of objects
within objects.
MyClass obj = new MyClass
{
NestedProperty = new NestedClass
{
Property1 = value1,
Property2 = value2
}
};
4. Anonymous Types: Object initializers are often used with anonymous types to create objects
with ad-hoc structures, especially in LINQ queries.
var person = new { Name = "John", Age = 30 };
5. Collection Initializers: In addition to object initializers, C# also supports collection initializers,
which allow you to initialize collections (such as lists, arrays, and dictionaries) using a similar
syntax.
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
Object initializers provide a concise and readable way to initialize objects, especially when creating
objects with many properties or nested objects. They contribute to cleaner and more expressive
code, improving code maintainability and reducing verbosity.
Anonymous Type
In C#, an anonymous type is a type defined dynamically at compile-time without explicitly declaring a
class structure. Anonymous types are useful when you need to create simple data structures on the
fly without the overhead of defining a formal class.
1. Syntax: Anonymous types are defined using the new keyword followed by an object initializer
within curly braces {}. The compiler infers the type of each property based on the assigned
values.
2. Properties: Anonymous types have read-only properties. Once created, the properties cannot
be modified. The property names and types are determined by the names and types of the
assigned values.
3. Use Cases: Anonymous types are commonly used in LINQ queries when you want to project
data into a temporary structure for immediate use. They are also useful for passing data
between different parts of your code when defining a formal class would be overkill.
4. Equality: Anonymous types have value-based equality semantics. Two instances of the same
anonymous type are considered equal if their corresponding properties have the same values.
5. Scope: Anonymous types are generally scoped to the method or block in which they are
defined. They cannot be used outside of their defining scope.
6. Limitations: Anonymous types cannot contain methods or events. They also cannot be used
as method parameters or return types, as their type information is not available outside the
scope where they are defined.
Extension Methods
Extension methods in C# allow you to add new methods to existing types (classes, structs, or
interfaces) without modifying the original type. This feature enables you to "extend" the functionality
of classes or interfaces that you don't control or can't modify, such as framework types or types from
third-party libraries. Extension methods were introduced in C# 3.0.
2. Usage: Once defined, extension methods can be called as if they were instance methods of
the extended type. The compiler automatically binds the call to the appropriate extension
method based on the type of the first parameter
3. Visibility: Extension methods are accessible wherever the containing namespace is visible.
You don't need to import the namespace explicitly to use extension methods defined within it.
4. Extension Method Chaining: Extension methods can be chained together, allowing for fluent
API design and concise code.
5. Limitations: Extension methods cannot access private or protected members of the extended
type. They are also resolved statically, so they cannot be overridden in derived types.
6. Naming: It's a convention to name extension method classes with a suffix like "Extensions" to
make their purpose clear.
Lambda Expression
Lambda expressions in C# provide a concise way to write anonymous functions or delegates. They
are particularly useful for writing inline functions, especially when passing small pieces of code as
arguments to methods or for defining event handlers, LINQ queries, and more. Lambda expressions
were introduced in C# 3.0 as part of the language enhancements.
3. Single Statement: If the body of the lambda expression consists of a single statement, you
can omit the curly braces { }. The result of the expression is the result of the single statement.
4. Multiple Statements: If the body of the lambda expression contains multiple statements, you
must enclose them in curly braces { }. You can use the return keyword to return a value
explicitly.
5. Capture of Outer Variables: Lambda expressions can capture variables from the outer
scope (i.e., variables defined outside the lambda expression). The captured variables are kept
alive as long as the delegate that holds the lambda expression is alive.
6. Parameter Types: Lambda expressions can have implicit or explicit parameter types. If the
parameter types can be inferred from the context, you can omit them. Otherwise, you must
specify them explicitly.
Lambda expressions provide a concise and expressive way to define inline functions in C#. They are
widely used in modern C# programming, especially in LINQ queries, asynchronous programming with
async and await, event handling, and functional programming paradigms.
LINQ
LINQ (Language Integrated Query) is a powerful feature in C# that enables developers to query and
manipulate data using a SQL-like syntax directly within the C# language. LINQ was introduced in C#
3.0 as part of the .NET Framework 3.5.
1. Query Expressions: LINQ allows you to write query expressions that resemble SQL queries.
These expressions operate on collections of objects (e.g., arrays, lists, databases) and can
include operations like filtering, sorting, grouping, joining, and projecting data.
var result = from person in people
where person.Age > 18
select person.Name;
2. Standard Query Operators: LINQ provides a set of standard query operators (methods)
defined as extension methods in the System.Linq namespace. These operators allow you to
perform various operations on collections, such as Where, Select, OrderBy, GroupBy, Join,
Aggregate, and more.
3. Deferred Execution: LINQ queries use deferred execution, meaning that the query is not
executed immediately when it's defined. Instead, the query is executed when the results are
enumerated (e.g., when iterating over the query result with a foreach loop).
4. Integration with Lambda Expressions: LINQ can be used with lambda expressions to
provide more concise and flexible syntax for writing queries. Lambda expressions allow you to
define inline functions for filtering, projecting, and sorting data.
5. LINQ to Objects: LINQ can be used to query in-memory collections such as arrays, lists, and
dictionaries. LINQ to Objects provides standard query operators for querying and
manipulating these collections.
6. LINQ to SQL, LINQ to Entities: LINQ can be used to query relational databases using LINQ
to SQL or LINQ to Entities. LINQ to SQL translates LINQ queries into SQL queries and
executes them against the database, while LINQ to Entities works with Entity Framework to
query and manipulate data stored in a database.
7. LINQ to XML: LINQ provides support for querying and manipulating XML documents using
LINQ to XML. LINQ to XML allows you to write queries to search, filter, transform, and create
XML documents.
LINQ is a versatile and powerful feature in C# that simplifies data querying and manipulation,
improves code readability, and reduces the amount of boilerplate code needed for common data
operations. It's widely used in various types of applications, including desktop, web, and mobile
development.
Partial Methods
Partial methods in C# are methods that allow for separation of the method declaration (signature)
from the method implementation. They enable you to define a method in one part of a partial class
and provide the implementation in another part of the class, or optionally not provide an
implementation at all. Partial methods are primarily used in code generation scenarios, such as when
working with visual designers or auto-generated code.
1. Declaration: Partial methods are declared using the partial keyword in one part of a partial
class. The method signature is defined without specifying the method body.
public partial class MyClass
{
partial void MyPartialMethod();
}
3. Optional Implementation: Partial methods are optional, meaning that you can define them in
one part of the class and choose not to provide an implementation in another part. In this
case, the method call is removed by the compiler, and any calls to the method are effectively
no-ops.
4. Usage: Partial methods are commonly used in code generated by visual designers, such as
Windows Forms or WPF designers in Visual Studio. They provide a way for developers to
extend or customize the behavior of auto-generated code without modifying the generated
code itself.
5. Event Handlers: Partial methods are also used as event handlers, especially in scenarios
where the event may or may not have any subscribers. This allows for cleaner code and
better performance by avoiding unnecessary event invocation.
6. Return Type: Partial methods can have void return type only. They cannot have any other
return type, parameters, or access modifiers other than partial.
Partial methods provide a way to decouple method declaration from implementation, allowing for
flexibility in extending or customizing code generated by tools or frameworks. They help improve
code organization, readability, and maintainability, especially in large-scale projects or when working
with code generated by automated tools.
Dynamic Type
In C#, the dynamic type allows you to declare variables whose types are resolved at runtime rather
than compile time. This provides flexibility when working with types that are not known until runtime,
such as objects from dynamic languages, COM objects, or objects whose types are determined
dynamically.
1. Type Resolution at Runtime: When a variable is declared as dynamic, the type of the
variable is determined at runtime rather than compile time. This means that method and
property resolution for dynamic variables is also deferred until runtime.
dynamic dynamicVariable = 10;
dynamicVariable = "Hello";
3. Late Binding: Operations on dynamic variables are resolved at runtime through late binding,
meaning that method calls and property accesses are resolved dynamically based on the
actual type of the object at runtime.
6. Use Cases: The dynamic type is particularly useful when working with interoperability
scenarios, such as calling dynamic languages like Python or JavaScript from C#, working with
COM objects, or dealing with data from external sources where the schema is not known until
runtime.
While the dynamic type provides flexibility in certain scenarios, it should be used judiciously, as it
bypasses compile-time type checking and can lead to harder-to-debug runtime errors if misused. It's
typically best to use dynamic only when interacting with truly dynamic or unknown types, and to favor
statically typed code wherever possible for improved safety and performance.
Optional and named parameters in C# provide flexibility and readability when working with method
parameters. Here's a breakdown of each feature:
Optional Parameters:
Optional parameters allow you to specify default values for parameters in method declarations. If a
value is not provided when the method is called, the default value is used.
They are defined in method signatures by assigning a default value to parameters.
All optional parameters must be at the end of the parameter list.
Example:
public void SendMessage(string message, int priority = 1)
{
Console.WriteLine($"Message: {message}, Priority: {priority}");
}
Named Parameters:
Named parameters allow you to specify arguments by name when calling methods, rather than by
position.
This provides clarity and flexibility, especially when methods have many parameters or the order of
parameters is not obvious.
Named parameters are specified by providing the parameter name followed by a colon (:) before the
argument.
Example:
public void DisplayInfo(string name, int age)
{
Console.WriteLine($"Name: {name}, Age: {age}");
}
Example:
public void SendEmail(string to, string subject = "Hello", string cc = "")
{
Console.WriteLine($"To: {to}, Subject: {subject}, CC: {cc}");
}
// Calling the method with named parameters and skipping optional parameters
SendEmail("[email protected]", cc: "[email protected]"); // Output: To:
[email protected], Subject: Hello, CC: [email protected]
Optional and named parameters enhance code readability and maintainability by allowing for more
expressive method calls. However, they should be used judiciously to avoid confusion, especially in
public APIs where parameter changes may affect existing callers.
Async | Await
In C#, the async and await keywords are used to write asynchronous code in a more straightforward
and readable manner. Here's how they work:
Async Methods:
The async modifier is used to define asynchronous methods. These methods can perform time-
consuming operations without blocking the calling thread.
Await Operator:
Inside an async method, the await operator is used to asynchronously wait for the completion of
another asynchronous operation, such as a Task or Task<T>.
Awaiting Task:
When calling an async method, you use the await keyword before the method call. This allows the
calling method to asynchronously wait for the completion of the async method.
Exception Handling:
Async methods can use regular try-catch blocks to handle exceptions. Exceptions thrown during
asynchronous operations are captured and propagated as if the code were synchronous.
try
{
string result = await DownloadDataAsync();
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
Performance Benefits:
Asynchronous programming with async and await can improve the responsiveness and
scalability of applications, especially in scenarios involving I/O-bound or CPU-bound
operations.
Async and await keywords provide a more natural way to write asynchronous code in C#,
making it easier to understand and maintain. They are widely used in modern C#
applications for handling asynchronous operations efficiently and elegantly.