Archivo por meses: junio 2015

10 consejos para programadores C#.Net

En esta entrada daremos 10 consejos para programadores C#.Net que puedan ser de utilidad y que en muchos casos no son muy conocidos.

Desarrollo y programación .net
Programador .Net
Consejo 1: Escribir pruebas unitarias para métodos no públicos

Seguro que si trabajas con proyectos que requieren un control de calidad has tenido que introducir algún proyecto de tests que impliquen pruebas unitarias. En ese caso seguro que has tenido problemas al intentar probar algún método que no es público. C# permite hacer visibles los ensamblados internos a otros ensamblados. Para solucionarlo añadiremos el siguiente atributo en el AseemblyInfo.cs.

//Hacer visible a un determinado ensamblado
[assembly: InternalsVisibleTo("MyTestAssembly")]
Consejo 2: Usar tuplas

En ocasiones es mejor utilizar una tupla contenedora de valores tipados que utilizar clases POCO, sobre todo cuando la estructura de datos creada solo se va a utilizar en un momento puntual.

public Tuple<int, string, string> GetEmployee()
{
	int employeeId = 1001;
	string firstName = "Rudy";
	string lastName = "Koertson";

	//Crear una tupla y devolverla
	return Tuple.Create(employeeId, firstName, lastName);
}
Consejo 3: No hay necesidad de crear colecciones temporales, mejor usar yield

Habitualmente creamos estructuras temporales de tipo enumerables para devolverlas en un método. Algo parecido a lo siguiente:

public List<int> GetValuesGreaterThan100(List<int> masterCollection)
{
	List<int> tempResult = new List<int>();

	foreach (var value in masterCollection)
	{
		if (value > 100)
			tempResult.Add(value);
	}
	return tempResult;
}

En estos casos podemos ahorrar un par de líneas de código utilizando el comando yield. A continuación mostramos el ejemplo anterior pero usando yield:

public IEnumerable<int> GetValuesGreaterThan100(List<int> masterCollection)
{
	foreach (var value in masterCollection)
	{
		if (value > 100)
			yield return value;
	}
}
Consejo 4: Comunicar que el método está obsoleto

Si tu librería está siendo usada por diferentes clientes y deseas que algún método deje de ser utilizado porque existe otro método que los sustituye o simplemente porque ya no funciona puedes indicarlo con el siguiente atributo:

[Obsolete("Este método estará obsoleto pronto. Para reemplazarlo se puede utilizar el método XYZ.")]
public void MyComponentLegacyMethod()
{
	//Aquí la implementación
}

El código anterior provocaría una advertencia o warning en el código que invocara este método. Sin embargo si deseas que ya no se pueda utilizar de ninguna de las maneras utilizarías un parámetro adicional boleano como True.

[Obsolete("Este método estará obsoleto pronto. Para reemplazarlo se puede utilizar el método XYZ.", true)]
public void MyComponentLegacyMethod()
{
	//Aquí la implementación
}
Consejo 5: Recuerda que las consultas de linq son diferidas

Cuando se realiza una consulta en linq solo se ejecuta realmente cuando se accede a los resultados. Esto se llama ejecución diferida. Para que solo se ejecute una vez la consulta debemos utilizar el método ToList.

public void MyComponentLegacyMethod(List<int> masterCollection)
{
	//Sin el método ToList esta consulta de linq sería ejecutada dos veces
	var result = masterCollection.Where(i => i > 100).ToList();

	Console.WriteLine(result.Count());
	Console.WriteLine(result.Average());
}
Consejo 6: Convertir entidades de negocio usando la palabra clave Explicit

Usar Explicit para definir la conversión de entidades. El método de conversión será invocado cuando se necesite. Un ejemplo:

class Program
{
	static void Main(string[] args)
	{
		ExternalEntity entity = new ExternalEntity()
		{
			Id = 1001,
			FirstName = "Dave",
			LastName = "Johnson"
		};
		MyEntity convertedEntity = (MyEntity)entity;
	}
}

class MyEntity
{
	public int Id { get; set; }
	public string FullName { get; set; }

	public static explicit operator MyEntity(ExternalEntity externalEntity)
	{
		return new MyEntity()
		{
			Id = externalEntity.Id,
			FullName = externalEntity.FirstName + " " + externalEntity.LastName
		};
	}
}

class ExternalEntity
{
	public int Id { get; set; }
	public string FirstName { get; set; }
	public string LastName { get; set; }
}
Consejo 7: Mantener el Stack Trace original

En .Net cuando se usa un bloque catch para capturar una excepción y se vuelve a lanzar se pierde información ya que se entiende que se ha controlado y que la excepción se genera desde el bloque que la capturó. Ejemplo:

public void RunDataOperation()
{
	try
	{
		Intialize();
		ConnectDatabase();
		Execute();
	}
	catch (Exception exception)
	{
		throw exception;
	}
}

Para mantener la traza original del error haremos esto:

public void RunDataOperation()
{
	try
	{
		Intialize();
		ConnectDatabase();
		Execute();
	}
	catch (Exception)
	{
		throw;
	}
}
Consejo 8: Atributo Flags – Agrupamiento de enum

Mediante el atributo Flags dentro de una enumeración permitirá agrupar los valores de enum. A continuación un ejemplo en el que la salida será: “BlackMamba, CottonMouth, Wiper“.

class Program
{
	static void Main(string[] args)
	{
		int snakes = 14;
		Console.WriteLine((Reptile)snakes);
	}
}

[Flags]
enum Reptile
{
	BlackMamba = 2,
	CottonMouth = 4,
	Wiper = 8,
	Crocodile = 16,
	Aligator = 32
}
Consejo 9: Forzar el tipo base para un tipo genérico

Partamos de que hemos creado una clase genérica donde hay que cumplir que el tipo genérico previsto en la clase debe heredar de una interfaz específica, esto se puede hacer como se muestra en el ejemplo siguiente:

class MyGenricClass<T> where T : IMyInterface
{
	//Cuerpo de la clase iría aquí
}

O incluso a nivel de método:

class MyGenricClass
{
	public void MyGenericMethod<T>(T t) where T : IMyInterface
	{
		//Implementación genérica iría aquí
	}
}
Consejo 10: Exponer una propiedad como IEnumerable no significa que sea solo lectura

Imaginemos que creamos una clase con una propiedad de tipo IEnumerable, en este caso es posible modificar esta propiedad aunque sea solo de lectura. Un ejemplo:

class Program
{
	static void Main(string[] args)
	{
		MyClass myClass = new MyClass();
		((List<string>)myClass.ReadOnlyNameCollection).Add("######From Client#####");

		myClass.Print();
	}
}

class MyClass
{
	List<string> _nameCollection = new List<string>();
	public MyClass()
	{
		_nameCollection.Add("Rob");
		_nameCollection.Add("John");
		_nameCollection.Add("Jummy");
		_nameCollection.Add("Derek");
	}
	public IEnumerable<string> ReadOnlyNameCollection
	{
		get { return _nameCollection.AsEnumerable(); }
	}

	public void Print()
	{
		foreach (var item in ReadOnlyNameCollection)
		{
			Console.WriteLine(item);
		}
	}
}

En el código anterior hemos podido comprobar que la lista ha podido ser modificada cuando nuestra intención es que fuera solo de lectura. Para remediar esto podemos utilizar lo siguiente:

public IEnumerable<string> ReadOnlyNameCollection
{
	get { return _nameCollection.AsReadOnly(); }
}
10 consejos para programadores C#.Net
5 (100%) 4 votes