• Featured post

C# Async ops

El nucleo de la programacion asincrona son los objetos Task y Task<T>. Ambos son compatibles con las palabras clave async y await.

Primero hay que identificar si el codigo se usa para trabajos enlazados a I/O o si estos son CPU intensivos.

  • Si el codigo espera algo como una BBDD o una response de un servidor, es codigo I/O. En este caso hay que usar async y await
  • Si el codigo realiza un calculo costoso, es CPU intensivo. Use await para esperar una operacion que se ha comenzado en background con Task.run

Read More

C# 12 primary constructors

A concise syntax to declare constructors whose params are available anywhere in the body.

Primary constructors is an easier way to create a constructor for your class or struct, by eliminating the need for explicit declarations of private fields and bodies that only assign param values.

They are great when you just need to do simple initialization of fields and for dependency injection.

Code example without primary constructors

public class BookDefault
{
	public int Id { get; }
	public string Title { get; }
	public int Pages { get; set; }
	private readonly List<decimal> ratings = new List<decimal>();
	public decimal? AverageRating => ratings.Any() ? ratings.Average() : 0m;

	public BookDefault(int id, string title, IEnumerable<decimal>? rating = null)
	{
		ArgumentException.ThrowIfNullOrEmpty(id);
		ArgumentException.ThrowIfNullOrEmpty(title);
		
		Id = id;
		Title = title;
		if(rating?.Any() == true)
		{
			ratings.AddRange(rating);
		}
	}
}

Code example using primary constructors

public class Book(int id, string title, IEnumerable<decimal> ratings)
{
	public int Id => id;
	public string Title => title.Trim();
	public int Pages { get; set; }
	public decimal AverageRating => ratings.Any() ? ratings.Average() : 0m;
}

another example

public class Person(string firstName, string lastName)
{
	public string FirstName { get; } = firstName;
	public string LastName { get; } = lastName;
}

Read More

C# 12 collection expressions

Collection expressions try to unify all syntaxes for initializing different collections. With them you can use the same syntax to express collections in a consistent way.

They replace all of this:

// all these versions are equivalent - the compiler generates identical code for each version
var numbers1 = new int[3] {1, 2, 3};
var numbers2 = new int[] {1, 2, 3};
var numbers3 = new[] {1, 2, 3};
int[] numbers4 = {1, 2, 3};

Using the new collection expressions (they cannot be used with var. You must declare the type)

// create an array
int[] intArray = [1, 2, 3, 4, 5];
// create empty array
int[] emptyArray = [];
// create a list
List<char> charList = ['D', 'a', 'v', 'i', 'd'];
// create a 2D list
List<int> int2dList = [[1, 2, 3], [4, 5, 6,], [7, 8, 9]];

how to flatten collections

int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] flattenCollection = [.. row0, 100, .. row1];
foreach(element in flattenCollection)
{
	Console.Write($"{element}, ");
}
// 1, 2, 3, 100, 4, 5, 6,

Reference(s)

https://devblogs.microsoft.com/dotnet/refactor-your-code-with-collection-expressions/
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#collection-expressions

C# class vs struct vs record (reference types vs value types)

Reference types vs value types

Reference types are allocated on the heap and garbage-collected, whereas value types are allocated on the stack so their (de)allocation are generally cheaper.

Arrays of reference types contain just references to instances of the reference type residing on the heap. Value type arrays hold the actual instance of the value type. Value type arrays are much cheaper than reference type arrays.

Value types get boxed when cast to a reference type or one of the interfaces they implement. They get unboxed when cast back to the value type. Boxes are objects that are allocated on the heap and are garbage-collected. Too much boxing and unboxing can have a negative impact.
In contrast, no such boxing occurs for reference types.

Reference type assignments copy the reference, whereas value type assignments copy the entire value. Assignments of large reference types are cheaper than assignments of large value types.

Reference types are passed by reference, whereas value types are passed by value. Changes to an instance of a reference type affect all references pointing to the instance. Value type instances are copied when they’re passed. When an instance of a value type is changed, it doesn’t affect any of its copies.

You can’t have a null value type. “null” only means a memory address reference is missing.

Class

Class is a reference type. When you compare reference types, this comparison checks if the compared objects are the same object (heap location).

You can specify access modifier if required (private, public, protected, internal).

class declaration

class Person
{
	public string Name {get; set;}
	public int Age {get; set;}
}

create an object

Person person = new Person();
person.Age = 30;
person.Name = "Mario";
Console.WriteLine(person.Name + " " + person.Age); // Mario 30

create another object using the first object we created

Person person2 = person; 
person2.Age = 29;
Console.WriteLine(person.Name + " " + person.Age); // Mario 29
Console.WriteLine(person2.Name + " " + person2.Age); // Mario 29

Read More

Interact with your pods

This details various ways that you can interact with the code and data running inside your pod.

Access a Pod via Network

If you want access to a specific pod, even if it’s not serving traffic on the internet. To achieve this, Kubernetes has support built into it.

kubectl port-forward <pod-name> <localport>:<podport>
kubectl port-forward istio 5015:80

A secure tunnel is created from your local machine, though the K8s master, to the instance of the Pod running on one of the worker nodes.

Getting More Info with Logs

When you need to debug.

# downloads the current logs from the running instance
kubectl logs kuard

# continuously streams logs
kubectl logs -f kuard

# get logs from a previous instance of the container. Useful if your containers are continuously restarting at startup. 
kubectl logs kuard --previous
  • -c if you have multiple containers in your Pod, you can choose the one to view

Read More

RDF and SPARQL

RDF (Resource Description Framework) - modelo de datos para representar datos como grafos (datos interconectados). Está dirigido y etiquetado para representar la información en la web.

SPARQL - query language estandarizado para consulta de grafos RDF.

Cuando trabajan ambos juntos, RDF y SPARQL te permiten construir aplicaciones de grafos.

What’s an RDF Graph?

This just means data represented using the RDF data model. This is what an example of such graph may look like

rdf-1

An RDF grahp is a directed graph consisting of nodes which are connected together by crearly labelled relationships with directionality. These relationships are known as edges. These edges connect one node to another.

Read More

How to import from JSON to Excel

It’s possible to import directly from JSON to Excel. This allows us to easily filter by some JSON fields or execute Excel queries on top of our JSON data.

I have a json file with hundreds of items following this structure.

{
	"_id": "63371b0027484f4f9f00587d",
	"guid": "ab4059e7-6441-4593-8272-42c53e4742d2",
	"isActive": true,
	"balance": "$2,120.18"
}

Read More

Introduction to GraphQL

What’s GraphQL?

A query language to build & query APIs. Invented by facebook in 2012, to solve its complexity in REST APIs.

It’s a good fit for companies where there’re tons of data we’d need otherwise to access through REST APIs. It’s not a replacement for REST, it’s an alternative for projects with large data sets.

GraphQL vs REST APIs

REST API

underfetching

Let’s say we want to retrieve the posts for a user and then, the comments and likes for a user’s post. In a REST API we’d have the following:

api/users/{id}/posts
api/users/{id}/posts/{postId}/comments
api/users/{id}/posts/{postId}/likes

With a single endpoint we cannot retrieve all the data. We need to call multiple endpoints to have all data we need.

overfetching

Let’s say I want to iterate the PostDescription for one user posts history. If I call the following endpoint it will give to me way more data than I need:

api/users/{id}/posts

gives back:

PostDescription UserId UserImage PostId PostCreationTime PostLocation etc.

This is way more data than I need to iterate and useless to me.

Read More

Windows debug errores

Visor de eventos

Aqui se pueden ver logs de errores y warnings. Interesantes son las carpetas de Registros de Windows - Aplicacion y Sistema windows-debug-1

Administrador de dispositivos

Si hay fallos de red aqui se puede ver el estado de los Adaptadores de Red: windows-debug-2

Dependency injection w. multiple implementations

I have the class package with a type, plus more info not relevant to the question

public class Package
{
	public string Type { get; set; }
	// ... more package properties
}

I have the following interface service to mail packages

public interface IMailService
{
	public Task<string> SendPackage(Package package);
}

Then I have several implementations for this interface

public class MailNewPackageService : IMailService
{
	public async Task<string> SendPackage(Package package)
	{
		Console.WriteLine("send package through new service");
		// implementation ...
	}
}

public class MailOldPackageService : IMailService
{
	public async Task<string> SendPackage(Package package)
	{
		Console.WriteLine("send package through old service");
		// implementation ...
	}
}

Read More

C# Streams and Files

MemoryStream

Los streams en memoria se usan sobre todo para leer de ficheros, o para almacenar información que queremos guardar en ficheros.

Si se inicializa mediante el siguiente constructor no se puede cambiar su tamaño.

MemoryStream ms = new MemoryStream(150);
ms.Capacity;
ms.Length;
ms.Position;

// 0 bits from Begin
ms.Seek(0, SeekOrigin.Begin);
// 5 bits from current position
ms.Seek(5, SeekOrigin.Current);
// go back 10 bits from current position
ms.Seek(-10, SeekOrigin.Current);

Files

Ejemplo para leer y escribir un fichero.

write file

FileStream fsEscribir = new FileStream("miArchivo.txt", FileMode.Create);

string cadena = "this is an example";

fsEscribir.Write(ASCIIEncoding.ASCII.GetBytes(cadena), 0, cadena.Length);
fsEscribir.Close();

read file

byte[] infoArchivo = new byte[100];

FileStream fs = new FileStream("miArchivo.txt", FileMode.Open);
fs.Read(infoArchivo, 0, (int) fs.Length);

Console.WriteLine(ASCIIEncoding.ASCII.GetString(infoArchivo));
Console.ReadKey();

fs.Close();