Classes
A class is the most common kind of reference type which contains fields and
methods,properties,indexers, events, constructors as members.It defines the properties of an object.
The simplest possible class declaration is as follows:
class YourClassName
A more complex class optionally has the following:
Preceding the keyword
class
Attributes and class modifiers. The non-nested class modifiers are public,
internal, abstract, sealed, static, unsafe, and partial
Following YourClass
Name
Generic type parameters, a base class, and interfaces
Within the braces Class members (these are methods, properties, indexers, events, fields, constructors,
overloaded operators, nested types, and a finalizer)
Fields
A field is a variable that is a member of a class or struct. For example:
class Octopus
string name;
public int Age = 10;
Fields allow the following modifiers:
Static modifier -static
Access modifiers- public internal private protected
Inheritance modifier- new
Unsafe code modifier- unsafe
Read-only modifier- readonly
Threading modifier- volatile
Field initialization
Field initialization is optional. An uninitialized field has a default value (0, \0, null,
false). Field initializers run before constructors:
public int Age = 10;
Declaring multiple fields together
For convenience, you may declare multiple fields of the same type in a comma-
separated list. This is a convenient way for all the fields to share the same attributes
and field modifiers. For example:
static readonly int legs = 8,
eyes = 2;
Methods
A method performs an action in a series of statements. A method can receive input
data from the caller by specifying parameters and output data back to the caller by
specifying a return type. A method can specify a void return type, indicating that it
doesn’t return any value to its caller. A method can also output data back to the
caller via ref/out parameters.
A method’s signature must be unique within the type. A method’s signature com-
prises its name and parameter types in order (but not the parameter names, nor the
return type)
Overloading methods
A type may overload methods (have multiple methods with the same name), as long
as the signatures are different. For example, the following methods can all coexist in
the same type:
void Foo (int x) {...}
void Foo (double x) {...}
void Foo (int x, float y) {...}
void Foo (float x, int y) {...}
However, the following pairs of methods cannot coexist in the same type, since the
return type and the params modifier are not part of a method’s signature:
void Foo (int x) {...}
float Foo (int x) {...} // Compile-time error
void Goo (int[] x) {...}
void Goo (params int[] x) {...} // Compile-time error
Instance Constructors
Constructors run initialization code on a class or struct. A constructor is defined
like a method, except that the method name and return type are reduced to the
name of the enclosing type:
public class Panda
string name; // Define field
public Panda (string n) // Define constructor
name = n; // Initialization code (set up field)
...
Panda p = new Panda ("Petey"); // Call constructor
Overloading constructors
A class or struct may overload constructors. To avoid code duplication, one con-
structor may call another, using the this keyword:
using System;
public class Wine
{
public decimal Price;
public int Year;
public Wine (decimal price) { Price = price; }
public Wine (decimal price, int year) : this (price) { Year = year; }
When one constructor calls another, the called constructor executes first.
Implicit parameterless constructors
For classes, the C# compiler automatically generates a parameterless public con-
structor if and only if you do not define any constructors. However, as soon as you
define at least one constructor, the parameterless constructor is no longer automati-
cally generated.
Nonpublic constructors
Constructors do not need to be public. A common reason to have a nonpublic con-
structor is to control instance creation via a static method call. The static method
could be used to return an object from a pool rather than necessarily creating a new
object, or return various subclasses based on input arguments:
public class Class1
Class1() {} // Private constructor
public static Class1 Create (...)
// Perform custom logic here to return an instance of Class1
...
Deconstructors (C# 7)
C# 7 introduces the deconstructor pattern. A deconstructor (also called a decon-
structing method) acts as an approximate opposite to a constructor: Whereas a con-
structor typically takes a set of values (as parameters) and assigns them to fields, a
deconstructor does the reverse and assigns fields back to a set of variables.
A deconstruction method must be called Deconstruct, and have one or more out
parameters, such as in the following class:
class Rectangle
public readonly float Width, Height;
public Rectangle (float width, float height)
Width = width;
Height = height;
public void Deconstruct (out float width, out float height)
width = Width;
height = Height;
To call the deconstructor, we use the following special syntax:
var rect = new Rectangle (3, 4);
(float width, float height) = rect; // Deconstruction
Console.WriteLine (width + " " + height); // 3 4
The second line is the deconstructing call. It creates two local variables and then
calls the Deconstruct method. Our deconstructing call is equivalent to:
float width, height;
rect.Deconstruct (out width, out height);
Or:
rect.Deconstruct (out var width, out var height);
Deconstructing calls allow implicit typing, so we could shorten our call to:
(var width, var height) = rect;
Or simply:
var (width, height) = rect;
If the variables into which you’re deconstructing are already defined, omit the types
altogether:
float width, height;
(width, height) = rect;
This is called a deconstructing assignment
The this Reference
The this reference refers to the instance itself.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//this refers to the current instance of itself.
namespace OOP
{
namespace thisns
{
public class Test
{
string name;
public Test(string name)//local parameter and field name are same local
parameter hides the field
{
this.name = name;
}
public string getName()
{
return name;
}
}
}
class thisdemo
{
public static void thisdemonstration()
{
thisns.Test t = new thisns.Test("praveen");
Console.WriteLine(t.getName());
}
}
}
Properties
Properties look like fields from the outside, but internally they contain logic, like
methods do. For example, you can’t tell by looking at the following code whether
CurrentPrice is a field or a property:
Stock msft = new Stock();
msft.CurrentPrice = 30;
msft.CurrentPrice -= 3;
Console.WriteLine (msft.CurrentPrice);
A property is declared like a field, but with a get/set block added. Here’s how to
implement CurrentPrice as a property:
public class Stock
decimal currentPrice; // The private "backing" field
public decimal CurrentPrice // The public property
get { return currentPrice; }
set { currentPrice = value; }
}
get and set denote property accessors. The get accessor runs when the property is
read. It must return a value of the property’s type. The set accessor runs when the
property is assigned.
Read-only and calculated properties
A property is read-only if it specifies only a get accessor, and it is write-only if it
specifies only a set accessor. Write-only properties are rarely used.
A property typically has a dedicated backing field to store the underlying data.
However, a property can also be computed from other data. For example:
decimal currentPrice, sharesOwned;
public decimal Worth
{
get { return currentPrice * sharesOwned; }
}
Automatic properties
The most common implementation for a property is a getter and/or setter that sim-
ply reads and writes to a private field of the same type as the property. An automatic
property declaration instructs the compiler to provide this implementation. We can
improve the first example in this section by declaring CurrentPrice as an auto-
matic property:
public class Stock
...
public decimal CurrentPrice { get; set; }
The compiler automatically generates a private backing field of a compiler-
generated name that cannot be referred to. The set accessor can be marked
private or protected if you want to expose the property as read-only to other
types.
Indexers
Indexers provide a natural syntax for accessing elements in a class or struct that
encapsulate a list or dictionary of values. Indexers are similar to properties, but are
accessed via an index argument rather than a property name. The string class has
an indexer that lets you access each of its char values via an int index:
string s = "hello";
Console.WriteLine (s[0]); // 'h'
Console.WriteLine (s[3]); // 'l'
Example creating your own indexer:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Indexers: Indexers are similiar to properties but they are accesed via an index
argument rather than property name.
//it is defined like an array.
namespace OOP
{
class Sentence
{
//string[] words = "The quick brown fox".Split();
char[] c = {'a','e','i','o','u'};
public char this[int wordNum]//definition of indexer
{
get { return c[wordNum]; }
set { c[wordNum] = value; }
}
}
class Indexers
{
public static void indexerdemo()
{
//string s = "Nepal";
//Console.WriteLine(s[1]);
Sentence s1 = new Sentence();
Console.WriteLine(s1[3]);
}
}
}
Constants
A constant is a static field whose value can never change. A constant is evaluated
statically at compile time and the compiler literally substitutes its value whenever
used (rather like a macro in C++). A constant can be any of the built-in numeric
types, bool, char, string, or an enum type.
A constant is declared with the const keyword and must be initialized with a value.
For example:
public class Test
{
public const string Message = "Hello World";
}