Programming Documentation

logo

Programming Documentation

Search
Light Mode
Contact Us

Contact us

No results for your search.
Sorry, an unexpected error occurred


C# is an object-oriented language that supports encapsulation, inheritance, and polymorphism. It allows classes to inherit from one parent class and implement multiple interfaces.


The override keyword is used to indicate methods that override virtual methods in a parent class. C# also has structs, which are lightweight classes that can implement interfaces but don't support inheritance.


C# provides record classes and record structs for data storage purposes. All types are initialized through constructors, either parameterless or primary constructors that declare required parameters for instance initialization.


Classes and objects

In C#, classes are fundamental types that combine state (fields) and actions (methods) into a single unit. They define the structure and behavior of objects. Classes support inheritance and polymorphism, allowing derived classes to extend and specialize base classes.


To create a class, you use class declarations that specify attributes, modifiers, class name, base class (if any), and implemented interfaces. The class body contains member declarations such as fields, methods, and properties.


Instances of classes are created using the `new` operator, which allocates memory, invokes a constructor to initialize the instance, and returns a reference to it. Memory management is automatic in C#, and objects are reclaimed when they are no longer reachable.


For example, a class called "Point" can be defined with its own set of properties and methods. Instances of this class can be created using the `new` operator.


It's worth noting that objects can be created and used throughout the application, and memory deallocation is handled by the runtime.


In summary, classes in C# provide a way to encapsulate data and behavior, support inheritance and polymorphism, and allow the creation of instances to represent objects in your program.


You can use the class as shown in the following code:


public class Point
{
    public int X { get; }
    public int Y { get; }
    
    public Point(int x, int y) => (X, Y) = (x, y);
}







Type parameters

Generic classes define type parameters. Type parameters are a list of type parameter names enclosed in angle brackets. Type parameters follow the class name. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of Pair are TFirst and TSecond:

public class Pair<TFirst, TSecond>
{
    public TFirst First { get; }
    public TSecond Second { get; }
    
    public Pair(TFirst first, TSecond second) => 
        (First, Second) = (first, second);
}






A class type that is declared to take type parameters is called a generic class type. Struct, interface, and delegate types can also be generic. When the generic class is used, type arguments must be provided for each of the type parameters:

var pair = new Pair<int, string>(1, "two");
int i = pair.First;     //TFirst int
string s = pair.Second; //TSecond string






A generic type with type arguments provided, like Pair<int,string> above, is called a constructed type.


Base classes

A class declaration may specify a base class. Follow the class name and type parameters with a colon and the name of the base class. Omitting a base class specification is the same as deriving from type object. In the following example, the base class of Point3D is Point. From the first example, the base class of Point is object:

public class Point3D : Point
{
    public int Z { get; set; }
    
    public Point3D(int x, int y, int z) : base(x, y)
    {
        Z = z;
    }
}







A class inherits the members of its base class. Inheritance means that a class implicitly contains almost all members of its base class. A class doesn't inherit the instance and static constructors, and the finalizer. A derived class can add new members to those members it inherits, but it can't remove the definition of an inherited member. In the previous example, Point3D inherits the X and Y members from Point, and every Point3D instance contains three properties, XY, and Z.


An implicit conversion exists from a class type to any of its base class types. A variable of a class type can reference an instance of that class or an instance of any derived class. For example, given the previous class declarations, a variable of type Point can reference either a Point or a Point3D:


Point a = new(10, 20);
Point b = new Point3D(10, 20, 30);







Structs

Classes define types that support inheritance and polymorphism. They enable you to create sophisticated behaviors based on hierarchies of derived classes.


By contrast, struct types are simpler types whose primary purpose is to store data values. Structs can't declare a base type; they implicitly derive from System.ValueType. You can't derive other struct types from a struct type. They're implicitly sealed.

// Some code







Namespaces

Namespaces in C# are used to organize code projects and prevent naming conflicts. They are identified by a dot (.) operator and can be nested. The `using` directive allows you to use types within a namespace without explicitly specifying the namespace for each class. The global namespace, represented as `global::`, refers to the root namespace. For example, `global::System` always refers to the .NET System namespace. Namespaces provide a way to structure and manage code, making it easier to organize and maintain large projects.


You can watch the video below to get a better understanding on why and how we use namespace :



📘
If you don't want to watch the video above, Check out "C# with Unity" section for a sample namespace code structure with unity.


Interfaces

An interface defines a contract that can be implemented by classes and structs. You define an interface to declare capabilities that are shared among distinct types. For example, the System.Collections.Generic.IEnumerable<T> interface defines a consistent way to traverse all the items in a collection, such as an array. An interface can contain methods, properties, events, and indexers. An interface typically doesn't provide implementations of the members it defines—it merely specifies the members that must be supplied by classes or structs that implement the interface.


Interfaces may employ multiple inheritance. In the following example, the interface IComboBox inherits from both ITextBox and IListBox.


interface IControl
{
    void Paint();
}

interface ITextBox : IControl
{
    void SetText(string text);
}

interface IListBox : IControl
{
    void SetItems(string[] items);
}

interface IComboBox : ITextBox, IListBox { }






Classes and structs can implement multiple interfaces. In the following example, the class EditBox implements both IControl and IDataBound.


interface IDataBound
{
    void Bind(Binder b);
}

public class EditBox : IControl, IDataBound
{
    public void Paint() { }
    public void Bind(Binder b) { }
}






When a class or struct implements a particular interface, instances of that class or struct can be implicitly converted to that interface type. For example


EditBox editBox = new();
IControl control = editBox;
IDataBound dataBound = editBox;







Enums

An Enum type defines a set of constant values. The following enum declares constants that define different root vegetables:

public enum SomeRootVegetable
{
    HorseRadish,
    Radish,
    Turnip
}






You can also define an enum to be used in combination as flags. The following declaration declares a set of flags for the four seasons. Any combination of the seasons may be applied, including an All value that includes all seasons:

[Flags]
public enum Jelly
{
    Happy = 0,
    Sad = 1,
    Hungry = 2,
    Cold = 4,
    All = Happy | Sad | Hungry | Cold
}






The following example shows declarations of both the preceding enums:

var turnip = SomeRootVegetable.Turnip;

var jellyMood = Jelly.Spring;
var jellyMoods = Jelly.Spring | Jelly.Autumn;
var jellyAllMoods = Jelly.All;






Nullable types

Variables of any type may be declared as non-nullable or nullable. A nullable variable can hold an additional null value, indicating no value. Nullable Value types (structs or enums) are represented by System.Nullable<T>. Non-nullable and Nullable Reference types are both represented by the underlying reference type. The distinction is represented by metadata read by the compiler and some libraries. The compiler provides warnings when nullable references are dereferenced without first checking their value against null. The compiler also provides warnings when non-nullable references are assigned a value that may be null. The following example declares a nullable int, initializing it to null. Then, it sets the value to 5. It demonstrates the same concept with a nullable string. For more information, see nullable value types and nullable reference types.

int? optionalInt = default; 
optionalInt = 5;
string? optionalText = default;
optionalText = "Hello World.";







Tuples

C# supports tuples, which provides concise syntax to group multiple data elements in a lightweight data structure. You instantiate a tuple by declaring the types and names of the members between ( and ), as shown in the following example:

Tuples provide an alternative for data structure with multiple members, without using the building blocks described in the next article.


📘
you can also check out the "Style Guide" Section to see how we use C# with Unity at P1-OM


On This Page