C# Classes

Auto properties

set vs private set

  • La variable que está como public ... { get; set; } se puede llamar de manera externa e interna.
  • Mientras que la variable public ... { get; private set; } se puede hacer un get de manera externa pero no se puede hacer set de manera externa

ejemplo

public class Person
{
	public string Name { get; set; }
	public string Surname { get; private set; }

	public Person()
	{
		Name = "ctor name";
		Surname = "ctor surname";
	}

	public void SetInternalValues()
	{
		Name = "name internal value";
		// if we'd have public string Surname { get; } without set; 
		//  then we couldn't set Surname inside its own class either 
		Surname = "surname internal value";
	}
}
var person = new Person(); 
person.Name = "name external value";
// person.Surname = "this isn't possible"; // cannot be set as we use { private set; }

Herencia

Para heredar una clase y varias interfaces desde otra, primero se pone la clase y luego las interfaces.

public class Example : AnotherClass, IExample
{

}

Exceptions

How to create your custom Exception

public class MyException : ApplicationException
{
	public MyException() : base("This is my custom exception")
	{
	
	}
}

Generics

Usage

public class GenericList<T>
{
	public void Add(T input)
	{
	
	}
}

Interfaces

Ejemplo de implementacion

interface IEquatable<T>
{
	bool Equals(T obj); 
}

Classes vs Structs

More info (StackOverflow)

Ambas son muy similares. En su definición sólo cambia la keyword struct.

La diferencia es que las clases son tipos por referencia. Las estructuras son tipos por valor.

Las estructuras pueden trabajar como clases pero realmente son valores ubicados directamente en la pila y no referencias a la informacion que hay en memoria. Para matrices, listas o pilas de miles de clases, las estructuras son más eficientes porque no necesita crear la referencia.

public class Point
{
	public int X { get; set; }
	public int Y { get; set; }
}
public struct PointStruct
{
	public int X { get; set; }
	public int Y { get; set; }
}

(!) Atención ya que su uso cambia (!)

Para el ejemplo anterior, tenemos el siguiente código:

Class:

static void Main(string[] args) 
{
	Point punto = new Point();
	punto.X = 10;
	punto.Y = 8;

	SumaCoordenadas(punto);
	// X = 20; Y = 18;
}

static void SumaCoordenadas(Point punto)
{
	point.X = point.X + 10;
	point.Y = point.Y + 10;
}

Struct:

static void Main(string[] args) 
{
	PointStruct puntoStruct = new PointStruct();
	puntoStruct.X = 10;
	puntoStruct.Y = 8;

	SumaCoordenadas(puntoStruct);
	// X = 10; Y = 8;
}

static void SumaCoordenadas(PointStruct puntoStruct)
{
	point.X = point.X + 10;
	point.Y = point.Y + 10;
}

Tipos de Acceso

internal: Desde el mismo proyecto se tiene acceso, como si fuera public. Desde fuera del ensamblado (exportada como libreria) no se tiene acceso, como si fuera private.

protected internal: Mezcla de protected con internal.

Abstract class

Clase abstracta

public abstract class Vehiculos
{
	public void Mover()
	{
		Console.WriteLine("Moviendo {0} ruedas", Ruedas);
	}

	public abstract int Ruedas { get; }
}

Ejemplo de implementacion

public class Coche : Vehiculos
{
	public override int Ruedas
	{
		get { return 4; }
	}
}

Abstract vs Virtual

(Check this https://stackoverflow.com/questions/391483/what-is-the-difference-between-an-abstract-method-and-a-virtual-method and this https://stackoverflow.com/questions/14728761/difference-between-virtual-and-abstract-methods)

An abstract function cannot have functionality. Any child class must implement their own version of this method, however it’s too general to even try to implement in the parent class.

A virtual function implements a default solution but you can override it in a child class. Even then, you can still call the parent method.

public abstract class E
{
	public abstract void AbstractMethod(int i);

	public virtual void VirtualMethod(int i)
	{
		// Default implementation, which can be overriden.
	}
}
public class D : E
{
	public override void AbstractMethod(int i)
	{
		// You HAVE TO override this method.
	}

	public override void VirtualMethod(int i)
	{
		// You can delete this if you want and use parent's version. 
	}
}

Sealed Class

Las clases marcadas como sealed no se pueden usar como clase base. No se pueden usar para heredar. Por esta razón no pueden ser abstract.

public sealed class SealedClass
{

}

Extension methods

Es posible extender funcionalidad que echemos en falta a clases como string. Para ello se crea un extended method y desde donde lo queramos llamar solo hay que añadir el import.

extended method declaration

public static class MyExtension
{
	public static int WordCount(this string str)
	{
		return str.Split(new char[] { ' ', '.', '?'}),
			StringSplitOptions.RemoveEmptyEntries).Length;
	}
}

usage

// (import)
static void Main(string[] args)
{
	string s = "Hello World";
	int i = s.WordCount();
}

Expression bodied members

(Check: https://stackoverflow.com/questions/54098375/expression-bodied-members-vs-lambda-expressions)

We can use expression-bodied syntax to implement a shorter syntax for properties and (named) methods (syntactic sugar). This has nothing to do with Lambdas.

Example (ToString)

original method

public override string ToString()
{
	return $"{FullName}, {Age}";
}

expression-bodied syntax

public override string ToString() => $"{FullName}, {Age}";

Example2 (getters)

Otra variacion se puede usar para comprobaciones en getters y setters.

expression-bodied syntax

private int age;
public int Age2
{
	get => age;
	set => age = value > 0 ? value : throw new ArgumentOutOfRangeException(nameof(value));
}

Example3 (constructors)

Otro ejemplo para constructores:

original constructor

public Student(string name, string surname, int age)
{
	Name = name;
	Surname = surname;
	Age2 = age;
}

expression bodied syntax:*

public Student(string name, string surname, int age) => (Name, Surname, Age2) = (name, surname, age);

Destructores

Se ejecutan cuando CLR destruye los objetos de la clase. Se ejecuta cuando el recolector de basura limpia de una manera automática.

public class Punto
{
	// constructor
	public Punto()
	{

	}

	// destructor
	~Punto()
	{
	
	}
}

Sobrecarga de operadores

Es posible sobrecargar operadores para que operen con clases (sumar o restar clases).

definition

public class Punto
{
	// adds 1 whenever the operator '+' is used. 
	public static Punto operator + (Punto valor)
	{
		Punto nuevoPunto = new Punto();
		nuevoPunto.X = valor.X + 1;
		nuevoPunto.Y = valor.Y + 1;

		return nuevoPunto;
	}
}

usage

Punto punto = new Punto(200, 50);
punto = +punto;