Genéricos
Los genéricos en C# proporcionan una forma de crear definiciones para tipos y métodos que pueden ser parametrizados sobre otros tipos. Esto mejora la reutilización de código, la seguridad de tipos y el rendimiento (por ejemplo, evita conversiones en tiempo de ejecución). Considera el siguiente ejemplo de un tipo genérico que agrega una marca de tiempo a cualquier valor:
using System;
sealed record Timestamped<T>(DateTime Timestamp, T Value)
{
public Timestamped(T value) : this(DateTime.UtcNow, value) { }
}
Rust también tiene genéricos, como se muestra en el equivalente del ejemplo anterior:
use std::time::*;
struct Timestamped<T> { value: T, timestamp: SystemTime }
impl<T> Timestamped<T> {
fn new(value: T) -> Self {
Self { value, timestamp: SystemTime::now() }
}
}
Mira también:
Restricciones de tipo genérico
En C#, los tipos genéricos pueden ser restringidos usando la palabra clave where. El siguiente ejemplo muestra tales restricciones en C#:
using System;
// Nota: los registros implementan automáticamente `IEquatable`. La siguiente
// implementación muestra esto explícitamente para una comparación con Rust.
sealed record Timestamped<T>(DateTime Timestamp, T Value) :
IEquatable<Timestamped<T>>
where T : IEquatable<T>
{
public Timestamped(T value) : this(DateTime.UtcNow, value) { }
public bool Equals(Timestamped<T>? other) =>
other is { } someOther
&& Timestamp == someOther.Timestamp
&& Value.Equals(someOther.Value);
public override int GetHashCode() => HashCode.Combine(Timestamp, Value);
}
Lo mismo se puede lograr en Rust:
use std::time::*;
struct Timestamped<T> { value: T, timestamp: SystemTime }
impl<T> Timestamped<T> {
fn new(value: T) -> Self {
Self { value, timestamp: SystemTime::now() }
}
}
impl<T> PartialEq for Timestamped<T>
where T: PartialEq {
fn eq(&self, other: &Self) -> bool {
self.value == other.value && self.timestamp == other.timestamp
}
}
En Rust, las restricciones de tipo genérico se llaman bounds.
En la versión de C#, las instancias de Timestamped<T>
solo pueden crearse para
T
que implementen IEquatable<T>
ellos mismos, pero ten en cuenta que la
versión de Rust es más flexible porque Timestamped<T>
implementa condicionalmente PartialEq
. Esto significa que las instancias de
Timestamped<T>
aún pueden crearse para algunos T
que no son equiparables,
pero entonces Timestamped<T>
no implementará la igualdad a través de
PartialEq
para dicho T
.
Mira también: