lunes, 26 de mayo de 2008

Porque no hay referencias const en c#?

Jejejeee... los que conozcais C++ ya sabreis por donde voy... para los demás, os cuento...

En C++ se puede declarar un puntero (o una referencia, que en C++ no es lo mismo que un puntero, pero tampoco importa esto ahora) como const. Con eso le indicamos al compilador que el método que recibe el puntero no puede modificar los datos apuntados por éste.
Si la referencia apunta a un tipo simple (sin ánimo de ofender) como int o char, pues el compilador ya sabe lo que es "modificar" los datos... Por ejemplo, esto en C++ no compia:


void foo (const int* pValor)

{

*pValor = 10;

}

El compilador se queja con un claro mensaje de error (lo que ya es raro viniendo de C++): 'pValor' : you cannot assign to a variable that is const.

En el caso de que el puntero apunte a una clase... como sabe el compilador si un método modifica los datos de la clase? Imaginemos la siguiente clase:

class Perrito

{

int edad;

public:

inline void SetEdad(int anyos) { edad = anyos;}

inline int GetEdad() { return edad;}

};

Ahora imaginemos una función que trabaja con Perritos:

void foo (Perrito* pDog)

{

pDog->GetEdad();

}

Vale... la función es un poco raquítica, pero servirá... Esta funcion NO modifica el estado del objeto Perrito que se le pasa, por eso, si queremos podemos indicarlo expresamente, añadiendo const al parámetro pDog:

void foo (const Perrito* pDog) { ... }

Con esto le indicamos al compilador y al usuario de nuestra función, que foo NO modifica el estado del objeto Perrito que se le pase... Si estais compilando este código, no lo hagáis... no compila (y esta vez el mensaje ya es un mensaje típico de C++: 'Perrito::GetEdad' : cannot convert 'this' pointer from 'const Perrito' to 'Perrito &').

Entonces??? Donde está la gracia? Si añado const y el código no compila.... Bueno, no desesperemos, la gracia de todo está en que la clase Perrito es incompleta. Le falta indicar al compilador cuales son las funciones que NO modifican el estado del objeto. En concreto en este caso sabemos que la función GetEdad no modifica el estado del Perrito, mientras que la función SetEdad sí... entonces, en la clase Perrito cambiamos la definición de GetEdad:

inline int GetEdad() const { return edad;}

Ole! Ahora nuestro código si que compila: foo declara que NO modifica el estado del Perrito que recibe y, por ello el compilador sólo le va a dejar llamar a funciones declaradas explícitamente como const en la clase... si añado una llamada a SetEdad dentro de foo, entonces el compilador se me va a quejar ('Perrito::SetEdad' : cannot convert 'this' pointer from 'const Perrito' to 'Perrito &').

Bueno... así a grandes rasgos es como funciona el mecanismo de punteros (o referencias) const en C++ (luego hay ciertos añadidos como mutable, pero vamos lo básico es esto). Notar también que una función puede devolver un puntero const y entonces es quien recoge este valor devuelto el que no puede modificar el estado de los datos apuntados por el puntero.

Pues, ahora repito la pregunta: porque nunca se ha añadido este mecanismo en C#??? Para empezar nos ahorraríamos clases como la ReadOnlyCollection (mis funciones podrían recibir o devolver una const List<T>, p.ej.). De verdad... si alguien tiene alguna idea de porque nunca se ha añadido esta característica en C# que me lo diga!!

Saludos!

1 comentario:

Jane B dijo...

Great work dude.... keep it up...

asp net web services