es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Es posible restringir un método solo para registros?

Supongamos que tengo varios tipos de registro diferentes con una interfaz común, como sigue:

registro Rec1(
string Tag
) : IFoo;

registro Rec2(
int Num,
string Tag
) : IFoo;

registro Rec3(
bool Flag
) : IFoo
{
public string Tag { get; init; }
public double Value { get; init; }
}

// … otros …

interface IFoo
{
string Tag { get; }
}

Mi objetivo es escribir una función para actualizar la propiedad Tag a través de la clonación de registros.

Ahora bien, si se conociera el tipo, se podría escribir algo como esto:

private Rec2 Update(Rec2 rec, string tag)
{
return rec with { Tag = tag };
}

Sin embargo, me gustaría evitar escribir una gran cantidad de sobrecargas, por lo que me pregunto si hay una forma más genérica de lograrlo. Por ejemplo, me tentaría escribir lo siguiente:

private TRec Update(TRec rec, string tag) where TRec : IFoo
{
return rec with { Tag = tag };
}

Sin embargo, esto no se compilaría, porque TRec podría ser cualquier cosa (class, struct, etc.), no solo un registro donde se pueda usar la instrucción with. Por cierto, no hay una restricción de registro que pueda aplicar.

Entonces, ¿hay alguna solución alternativa? ¿Es algo que se espera que se resuelva en el futuro?

Como pregunta adicional (solo por curiosidad), ¿por qué una clase traducida de registro no está marcada con una interfaz especial para hacer que la instrucción with funcione?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para lograr el objetivo de actualizar la propiedad Tag mediante la clonación de registro para múltiples tipos de registro con una interfaz común, podemos usar el parámetro de tipo genérico where TRec : IFoo, TRec with como restricción para asegurar que TRec sea un tipo de registro que implemente IFoo y pueda usar la declaración with. La función actualizada se vería así:

    private TRec Update<trec>(TRec rec, string tag)
        where TRec : IFoo, TRec with
    {
        return rec with { Tag = tag };
    }
    

    En cuanto a por qué una clase traducida a record no tiene una interfaz especial marcada para hacer que la declaración with funcione, es porque los registros son una nueva característica en C# 9 y puede haber decisiones de diseño para mantener los registros más simples y livianos sin agregar interfaces o restricciones adicionales. Sin embargo, esto es solo una especulación y es posible que futuras actualizaciones de C# puedan introducir nuevas características para los registros.

Comments are closed.