Est-ce que C # ont un équivalent à la dactylographie structurelle de Scala?
-
26-09-2019 - |
Question
Scala, je peux définir des types de structure suivante comme suit:
type Pressable = { def press(): Unit }
Cela signifie que je peux définir une fonction ou une méthode qui prend comme quelque chose argument qui est Pressable, comme ceci:
def foo(i: Pressable) { // etc.
L'objet que je passe à cette fonction doit avoir défini pour une méthode rapide appelée () qui correspond à la signature de type défini dans le type - prend aucun argument, renvoie l'unité (la version de Scala de vide)
.Je peux même utiliser la ligne de type structural:
def foo(i: { def press(): Unit }) { // etc.
Il permet essentiellement le programmeur d'avoir tous les avantages de frappe de canard tout en ayant l'avantage de la vérification du type de compilation.
Est-ce que C # a quelque chose de similaire? J'ai googlé mais ne trouve rien, mais je ne suis pas familier avec C # en profondeur. S'il n'y a pas, est-il prévu d'ajouter cela?
La solution
Non, et pas de plans que je connais. Seulement nommé (plutôt que de structure) de sous-typage (par exemple des interfaces).
(D'autres peuvent vouloir voir aussi
http://en.wikipedia.org/wiki/Nominative_type_system
http://en.wikipedia.org/wiki/Structural_type_system
)
(Quelques personnes peuvent signaler quelques cas d'angle exotiques, comme la déclaration de foreach
en utilisant le typage structurel pour GetEnumerator
, mais c'est la noreferrer exception plutôt que la règle.)
Autres conseils
Il n'y a pas un moyen de définir les types de structure qui a une fonction particulière. Il y a une bibliothèque qui ajoute le support de frappe de canard à C # qui se trouve .
Ceci est l'exemple de Duck projet de frappe. S'il vous plaît noter que le frappe de canard arrive à l'exécution et peut échouer . Je crois comprendre aussi que cette bibliothèque génère des proxys pour les types qui sont tapés canard, qui est bien loin de l'élégant support de compilation qui est apprécié à Scala. Ceci est probablement aussi bon qu'il obtient avec cette génération de C #.
public interface ICanAdd
{
int Add(int x, int y);
}
// Note that MyAdder does NOT implement ICanAdd,
// but it does define an Add method like the one in ICanAdd:
public class MyAdder
{
public int Add(int x, int y)
{
return x + y;
}
}
public class Program
{
void Main()
{
MyAdder myAdder = new MyAdder();
// Even though ICanAdd is not implemented by MyAdder,
// we can duck cast it because it implements all the members:
ICanAdd adder = DuckTyping.Cast<ICanAdd>(myAdder);
// Now we can call adder as you would any ICanAdd object.
// Transparently, this call is being forwarded to myAdder.
int sum = adder.Add(2, 2);
}
}
Ceci est la voie C # de réaliser la même chose en utilisant le bon vieux interfaces ennuyeux.
interface IPressable {
void Press();
}
class Foo {
void Bar(IPressable pressable) {
pressable.Press();
}
}
class Thingy : IPressable, IPushable, etc {
public void Press() {
}
}
static class Program {
public static void Main() {
pressable = new Thingy();
new Foo().Bar(pressable);
}
}
Comme d'autres ont noté, ce n'est pas vraiment disponible dans .NET (comme cela est plus une question de l'exécution d'une langue). Cependant, .NET 4.0 pour supports chose similaire interfaces COM importées et je crois que cela pourrait être utilisé pour la mise en œuvre pour la saisie de structure .NET. Voir ce billet de blog:
Je n'ai pas essayé de jouer avec moi-même, mais je pense qu'il pourrait permettre aux auteurs d'écrire compilateur langues avec la saisie de structure pour .NET. (L'idée est que vous (ou un compilateur) définiriez une interface derrière la scène, mais cela fonctionnerait, parce que les interfaces seraient traitées comme équivalentes grâce à la fonction d'équivalence COM).
En outre, C # 4.0 prend en charge le mot-clé dynamic
qui, je pense, pourrait être interprété comme un typage structurel (sans vérification de type statique). Le mot-clé vous permet d'appeler des méthodes sur un objet sans knowning (à la compilation) si l'objet aura les méthodes nécessaires. Ceci est essentiellement la même chose que le projet « frappe de canard » mentionné par Igor (mais qui est, bien sûr, pas un typage structurel approprié).
Le modèle awaitable en C # peut-être interprété comme une limitation, ad hoc instance de sous-typage structurel / frappe existentielle. Le compilateur ne await
objets qui ont accès à une méthode de GetAwaiter()
que les rendements tout objet INotifyCompletion
avec un ensemble spécifique de méthodes et propriétés. Etant donné que ni l'objet « awaitable » ni l'objet « awaiter » doit mettre en œuvre une interface (sauf INotifyCompletion
dans le cas de celui-ci), await
est similaire à une méthode qui accepte des objets awaitable structurellement tapé.