2017-07-09 4 views
2

J'apprends C# et j'ai un exercice avec ces trois classes:Dictionnaire sans médicaments génériques

public abstract BaseClass<T> Where T : BaseClass<T> 

public class Class1 

public class Class2 : BaseClass<Class2> 

Sur l'exercice il y a ceci:

var dictionary = new Dictionary { [class1] = class1, [class2] = class2 }; 

Je pense que là, Dictionary est un raccourci pour Dictionary<object, object> ; donc j'ai ajouté cette classe au projet:

public class Dictionary : Dictionary<object, object> 

Mon problème ici est que je ne sais pas si je l'ai déclaré correctement Dictionary. Maintenant l'exercice fonctionne parfaitement mais peut-être il y a une autre option pour déclarer Dictionary. En passant, j'ai utilisé dynamic au lieu de object et cela fonctionne aussi.

Ma question est:

Dans l'exercice, est Dictionary une classe personnalisée ou une autre classe de .NET Framework ou tout autre que je ne sais pas?

+2

Il n'y a pas de classe 'Dictionary' non générique. Tu ne devrais pas faire ça. – SLaks

+0

@ SLaks Si je ne devais pas faire ça; que dois-je faire pour rendre var dictionnaire = new Dictionary {[class1] = class1, [class2] = class2}; 'compile? – VansFannel

+0

@SLaks C'est un très mauvais exercice. – stybl

Répondre

1

La syntaxe de l'exercice est invalide:

var dictionary = new Dictionary { 
    [class1] = class1 
, [class2] = class2 
}; 

Cela ressemble à un initialiseur de dictionnaire C# 6, qui s'attend à ce que les paramètres de type du dictionnaire soient spécifiés explicitement:

var dictionary = new Dictionary<object,object> { 
    [class1] = class1 
, [class2] = class2 
}; 

Vous n'avez pas besoin de créer votre propre classe dérivée de Dictionary<TKey,TVal>, ou d'utiliser dynamic.

Note: L'utilisationobject pour les deux type de clé et de la valeur est requise parce que votre exemple dictionnaire utilise des classes Class1 et Class2 comme les clés et valeurs, alors que les classes ont aucun ancêtre commun autre que object.

Edit:

Je ne peux pas modifier l'exercice. Donc, je dois faire quelque chose pour le compiler

Votre solution qui dérive de DictionaryDictionary<object,object> est bien alors. Vous pouvez également écrire votre propre classe Dictionary qui prend un initialiseur de type dictionnaire, mais ce serait un exercice beaucoup plus difficile.

+0

Je ne peux pas modifier l'exercice. Donc, j'ai besoin de faire quelque chose pour le compiler. Et je ne sais pas si la solution que j'utilise, c'est bon ou pas. Peut-être que je peux utiliser un alias aussi. Oui, je sais, c'est un très mauvais exercice. – VansFannel

+0

@VansFannel, j'ai fourni un extrait de code sur la façon de le faire dans ma réponse, veuillez vérifier ci-dessous. – ironstone13

+0

@dasblinkenlight, il semblerait que l'initialisateur de collection fonctionnera hors de la boîte si vous héritez du dictionnaire, bien que je convienne que dans la vraie vie, vous auriez très rarement besoin d'hériter réellement d'un dictionnaire. – ironstone13

1

Dans .NET Dictionary classe est générique, et il n'y a aucune autre classe nommée Dictionary dans BCL. Vous pouvez obtenir un formulaire de fonctionnalité similaire le predescessor - HashTable qui implémente également IDictionary Interface

Notez qu'il n'y a pas besoin d'hériter de Dictionnaire - il suffit d'utiliser l'instance de classe générique avec les types dont vous avez besoin, ou l'utilisation une Hashtable.

Si vous avez des doutes si une classe spécifique est dans la BCL ou non - vérifiez son espace de noms.

Si vous êtes curieux au sujet de son contrôle de la mise en œuvre reference source

Plus précisément pour votre exersise, il semble que vous devez hériter de dictionnaire et d'utiliser un collection initializer:

Note: Ne pas hériter de Dictionnaire dans code de production, la plupart du temps, il est inutile.

namespace ClassLibrary2 
{ 
    public class TestClass 
    { 
     public abstract class BaseClass<T> where T : BaseClass<T> {} 

     public class Class1 { } 

     public class Class2 : BaseClass<Class2> { } 

     private class Dictionary : Dictionary<Class1, Class2> { } 

     public void Test() 
     { 
      var dictionary = new Dictionary { { new Class1(), new Class2() } }; 
     } 
    } 
} 

Par ailleurs, ayant cette public abstract class BaseClass<T> where T : BaseClass<T> {} est un exemple de curiously recurring template pattern, @Eric Lippert a écrit un bel article sur ce point - voir Curiouser and curiouser

+1

Je n'ai aucun espace de noms à vérifier. Faire la ligne 'var dictionnaire = new Dictionnaire {[class1] = class1, [class2] = class2};' compiles fait partie de l'exercice. – VansFannel

+0

@VansFannel, pourquoi pas 'var dictionary = new Dictionary ();' – ironstone13

+0

Non, je ne peux pas changer le contenu de l'exercice. – VansFannel

0

La ligne

var dictionary = new Dictionary { [class1] = class1, [class2] = class2 }; 

utilise un initialiseur d'objet pour initialiser l'indexeur de la classe Dictionary. Cette syntaxe est prise en charge à partir de C# Version 6 (voir la spécification de langage C# 6.0 sous la section §7.6.11.2 Initialisateurs d'objet).

Comme vous l'avez correctement découvert, une façon d'obtenir une classe qui permet un tel comportement est de dériver une classe de Dictionary<T,K>. Une autre méthode consiste à écrire une classe Dictionary utilisant un indexeur. La classe la plus simple qui présente un tel comportement est:

public class Dictionary 
{ 
    public object this[object index] { 
     get {return null;} 
     set {} 
    } 
} 

static void Main() 
{ 
    Class1 class1 = new Class1(); 
    Class2 class2 = new Class2(); 
    var dictionary = new Dictionary 
    { 
     [class1] = class1, 
     [class2] = class2 
    }; 
} 

Ce qui ne fait rien, évidemment, mais il montre où la syntaxe d'initialisation provient.

+0

Merci. Est-ce mieux que d'hériter du dictionnaire? – VansFannel

+1

Dans le but d'avoir une mise en œuvre de travail, non. Mais c'est la solution la plus simple au problème donné. – Adrian