C# Classes

Auto properties

set vs private set

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

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; }

Exceptions

How to create your custom Exception

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

Classes vs Structs

Please check this post on class vs struct vs record.

Tipos de Acceso

internal: Visible solo dentro del mismo ensamblado. Útil para ocultar detalles de implementación que no deben ser públicos fuera de una libreria.
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: Más accesible que internal. Accesible o bien desde el mismo enamblado o bien desde una subclase hija.

Abstract class

Clase abstracta

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

	public abstract int Ruedas { get; }
}

Ejemplo de implementacion

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

Abstract vs Virtual

(For more information on the topic check this and also this one)

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 this for more information)

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));
}

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;