c# - una - ¿Cómo llamar al constructor sin nuevo?
sobrecarga de metodos en java (4)
Aunque puede hacerlo utilizando un implicit operator
, recomiendo encarecidamente que no lo haga. Strings
son animales especiales en C # y reciben un tratamiento especial, junto con otras clases especiales como int
y float
, puedes crearlas sin necesidad de actualizarlas explícitamente debido a la forma en que funciona el compilador de C #:
var myInt = 0;
var myFloat = 0f;
var myString = "string";
Sin embargo, este comportamiento generalmente se restringe a esas clases especiales. Agregar un implicit operator
para hacer esto es una mala práctica por varias razones:
- Oculta lo que realmente sucede debajo. ¿Estamos creando un
new Student
bajo el capó al convertir de unastring
? - No se puede mantener. ¿Qué sucede cuando tiene que agregar otro parámetro al constructor para incluir también el número de identificación del
Student
? - Elimina la posibilidad de usar variables implícitamente tipadas. No puedes llamar a
var student = "name"
; debe llamar alStudent student = "name"
.
El paradigma del implicit operator
se descompone muy rápidamente. Aunque es algo genial de hacer, te estás preparando para un mal momento y harás que tu código sea más difícil de leer. Aconsejaría simplemente usar el new Student("name")
como todos los demás objetos normales en C #.
Sé que la cadena es como una clase, y al crear una nueva cadena, la cadena en sí no debe el valor, sino solo el puntero del valor. pero al crear una cadena no es necesario usar la palabra nueva;
string a = "hello";
y no
string a = new string("hello");
Sé que la segunda opción también es posible, pero lo que quiero entender es ¿por qué la primera?
Digamos que tengo un estudiante de nombre de clase cuyo constructor obtiene una string
. Para crear una nueva clase, debo usar la palabra nueva salvada.
student example = new student("Sabrina");
Intenté overload oparator =
pero no es posible.
¿Cómo puedo crear una nueva clase como una string
(sin usar la palabra new
)?
student example = "Sabrina";
La cadena "hello"
en su código, en todos los casos, no implica una llamada a un constructor. Es un valor constante, creado en tiempo de compilación, de modo que todas las instancias de la cadena "hello"
son el mismo objeto. De forma similar, el entero 1
y el valor decimal 3.456
, y cualquier otro valor "literal", son constantes que existen antes del tiempo de ejecución, antes de que el código del constructor pueda ser invocado.
El código new string("hello");
no se puede invocar, ya que no hay ningún constructor de cadena que tome una cadena como valor. Sin embargo, si lo cambió a una new string("hello".ToCharArray());
, obtendrías un objeto de cadena, pero no será lo mismo que la cadena "hello"
. En realidad, has creado una nueva cadena, en una ubicación de memoria separada, del simple "hello"
. Solo sucede que tiene los mismos valores de caracteres contenidos en él como "hello"
.
La importancia es que, si utiliza el truco de conversión de tipo implícito, entonces un literal de cadena convertido a su tipo no será el mismo objeto:
class Foo
{
private string value;
public Foo(string val)
{
this.value = val;
}
public static implicit operator Foo(string value)
{
return new Foo(value);
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Foo a = "asdf";
Foo b = "asdf";
Assert.AreNotEqual(a, b);
}
}
En otras palabras, a.Equals(b)
devuelve falso. Para hacer que el método Equals sea verdadero, tendrás que anular el método Equals en tu clase Foo.
public override bool Equals(object obj)
{
return obj is Foo && value.Equals(((Foo)obj).value);
}
Pero, como se menciona en otros carteles, esto es una ofuscación. Harás que sea difícil usar el código y será difícil depurarlo. Cambia lo que parece una asignación regular a una llamada de método completa. Y rompe muchas de las herramientas que Visual Studio proporciona para inspeccionar el código, como F12 para pasar a una definición de método.
La conversión de tipo implícita debe usarse solo en los casos en que los dos tipos son en realidad bastante intercambiables en uso, con pequeñas diferencias en su funcionalidad. El tipo de float
puede convertir implícitamente a double
porque no hay métodos y funciones adicionales para el double
frente al float
, y aumentar la precisión de float
a double
no cambia el valor. Sin embargo, pasar del double
al float
requiere un lanzamiento explícito, porque la pérdida de precisión cambia el valor representado.
Podría tener un método llamado createObject () y usarlo mientras los constructores sean privados, desaconsejar su uso.
Puede usar el operador de conversión para implícitamente:
sealed class Student
{
public string Name
{
get;
private set;
}
Student()
{
}
public static implicit operator Student(string name)
{
return new Student
{
Name = name
};
}
}
Entonces puedes hacer Student student = "Sabrina";
.