Est-il possible de contraindre une méthode pour les enregistrements seulement?

0

La question

Supposons que j'ai plusieurs différents record-types avec une interface commune, comme suit:

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; }
}

Mon but est d'écrire une fonction pour mettre à jour la propriété Tag via record clonation.

Maintenant, si le type était connu, je pourrais écrire quelque chose comme ceci:

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

Cependant, je voudrais éviter d'écrire un tas de surcharges, alors je me demandais si il n'y a plus générique moyen pour y parvenir. Par exemple, j'avais tenté d'écrire que:

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

mais ça ne compile pas, parce que TRec pourrait être n'importe quoi (class, struct, etc), et pas seulement une record où je peux utiliser l' with l'énoncé. En passant, il n'y a pas un record-contrainte, je pourrait s'appliquer.

Donc, est-il une solution de contournement? est-il rien à attendre d'être résolu à l'avenir?

Comme une question bonus (juste pour le plaisir de la curiosité), pourquoi un record-traduit de classe n'est pas marquée par une interface spéciale, afin de rendre le with instruction de travail contre?

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

La meilleure réponse

1

Au lieu d'avoir une base vide record, ont tous ces dossiers héritent d'une base commune d'enregistrement, qui l'implémente l'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

D'accord, regarde mieux!
Mario Vernari

À mon humble avis, non seulement semble meilleure, mais en fait c'est mieux - non seulement vous n'êtes pas à l'aide d'un "marqueur" qui est une odeur de code, vous êtes réellement en utilisant l'héritage de la façon dont il devrait être utilisé.
Zohar Peled
0

Grâce à une autre réponse (voir le lien dans les commentaires), il semble être un hacky solution de contournement:

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 };
}

La contrainte est efficace en raison de la R record, tandis que la Tag grâce à la cession init accesseur.

Encore une fois, pour moi, c'est un peu comme un hack qu'une réelle solution. Je préfère voir quelques une prise en charge native.

2021-11-20 06:57:32

Dans d'autres langues

Cette page est dans d'autres langues

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