É possível restringir um método para apenas registros?

0

Pergunta

Vamos supor que eu tenha vários record-tipos, com um interface comum, como segue:

record Rec1(
    string Tag
    ) : IFoo;

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

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

// ... others ...

interface IFoo
{
    string Tag { get; }
}

Meu objetivo é escrever uma função para atualizar a Tag de propriedade através do registro clonation.

Agora, se o tipo eram conhecidos, eu poderia escrever algo como isto:

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

No entanto, eu gostaria de evitar a para escrever uma série de sobrecargas, então eu estou querendo saber se há uma forma mais genérica para o atingir. Por exemplo, eu seria tentado a escrever como:

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

mas isso não vai compilar, porque TRec poderia ser qualquer coisa (class, struct, etc.), não apenas um record onde eu posso usar o with instrução. A propósito, não há um record-restrição de que eu poderia aplicar.

Assim, existe alguma solução? é alguma coisa a esperar para ser resolvido no futuro?

Como um bônus questão (apenas para fins de curiosidade), por um record-traduzido classe não está marcado com uma interface especial, a fim de tornar o with instrução de trabalho contra?

c# constraints generics record
2021-11-20 05:42:41
2

Melhor resposta

1

Em vez de ter uma base vazia registro, tem todos esses registros herdar a partir de uma base comum de registro, que implementa a interface:

record R : IFoo ...

record Rec1 : R....
record Rec2 : R....

private TRec Update<TRec>(TRec rec, string tag) where TRec : R
{
    return rec with { Tag = tag };
}
2021-11-20 07:03:58

Concordo, parece melhor!
Mario Vernari

IMHO, não só parece melhor, mas, na verdade, é melhor - não só não está a utilizar um "marcador", que é um código de cheiro, na verdade você está usando herança e a forma como deve ser utilizado.
Zohar Peled
0

Graças a outra resposta (veja o link nos comentários), parece ser um hacky solução alternativa:

record R();

record Rec1(
    string Tag
    ) : R, IFoo;

// ... others ...

interface IFoo
{
    string Tag { get; init; }
}

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

A restrição é eficaz, devido a R registro, enquanto o Tag atribuição graças a init acessor.

Novamente, para mim, é muito parecido com um corte de uma solução real. Eu preferiria ver algumas suporte nativo.

2021-11-20 06:57:32

Em outros idiomas

Esta página está em outros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................