Question

Quelqu'un peut-il expliquer le comportement suivant?

En résumé, si vous créez plusieurs conforme CLS bibliothèques dans Visual Studio 2008 et leur demander de partager une racine d'espace de noms commun, une bibliothèque référence à une autre bibliothèque besoin références à cette les références de bibliothèque, même si elle ne les consomme pas.

Il est assez difficile d'expliquer en une seule phrase, mais voici les étapes pour reproduire le comportement (porter une attention particulière aux espaces de noms):

Créer une bibliothèque appelée Bibliothèque_A et ajouter une une seule classe à cette bibliothèque:

namespace Ploeh
{
    public abstract class Class1InLibraryA
    {
    }
}

Assurez-vous que la bibliothèque est conforme CLS en ajoutant [assembly: CLSCompliant(true)] à AssemblyInfo.cs.

Créer une autre bibliothèque appelée Bibliothèque_B et référence Bibliothèque_A. Ajouter les classes suivantes à Bibliothèque_B:

namespace Ploeh.Samples
{
    public class Class1InLibraryB : Class1InLibraryA
    {
    }
}

et

namespace Ploeh.Samples
{
    public abstract class Class2InLibraryB
    {
    }
}

Assurez-vous que Bibliothèque_B est également conforme CLS.

Notez que Class1InLibraryB dérive d'un type à Bibliothèque_A, alors que Class2InLibraryB ne fonctionne pas.

créer une troisième bibliothèque appelée LibraryC et référence Bibliothèque_B (mais pas Bibliothèque_A). Ajoutez la classe suivante:

namespace Ploeh.Samples.LibraryC
{
    public class Class1InLibraryC : Class2InLibraryB
    {
    }
}

Cela devrait encore compiler. Notez que Class1InLibraryC dérive de la classe dans Bibliothèque_B que ne pas utiliser tous les types de Bibliothèque_A .

Notez également que Class1InLibraryC est définie dans un espace de noms, qui fait partie de la hiérarchie d'espace de noms défini dans Bibliothèque_B.

Jusqu'à présent, LibraryC n'a pas de référence à Bibliothèque_A, et comme il utilise aucun type de Bibliothèque_A, la solution compile.

rendre conformes LibraryC CLS ainsi. Tout à coup, la solution ne compile plus, vous donnant ce message d'erreur:

  

Le type « Ploeh.Class1InLibraryA » est définie dans un assemblage qui ne sont pas référencés. Vous devez ajouter une référence à l'assembly 'Ploeh, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null'.

Vous pouvez faire la solution compiler à nouveau dans l'une des façons suivantes:

  • Supprimer CLS de conformité LibraryC
  • Ajoutez une référence à Bibliothèque_A (bien que vous n'avez pas besoin)
  • Changer l'espace de noms dans LibraryC de sorte qu'il ne fait pas partie de la hiérarchie de l'espace de noms de Bibliothèque_B (par exemple à Fnaah.Samples.LibraryC)
  • Changer l'espace de noms Class1InLibraryB (qui est, une pas d'occasion à partir LibracyC) afin qu'il soit ne réside pas dans la hiérarchie de l'espace de noms de LibraryC (par exemple à Ploeh.Samples.LibraryB)

Il semble qu'il y ait une certaine interaction étrange entre la hiérarchie des espaces de noms et la conformité CLS.

La résolution de ce problème peut être fait en choisissant l'une des options dans la liste ci-dessus, mais quelqu'un peut-il expliquer la raison derrière ce comportement?

Était-ce utile?

La solution

J'ai eu un coup d'oeil dans les documents officiels de la CLS ( http: // msdn.microsoft.com/en-us/netframework/aa569283.aspx ), mais ma tête a explosé avant que je puisse trouver une réponse simple.

Mais je pense que la base est que le compilateur, afin de vérifier la conformité de CLS de LibraryC, a besoin de se pencher sur les conflits de noms possibles avec Bibliothèque_A.

Le compilateur doit vérifier toutes les « parties d'un type qui sont accessibles ou visibles à l'extérieur de l'ensemble définissant » (CLS règle 1).

Depuis public class Class1InLibraryC hérite Class2InLibraryB, il doit vérifier la conformité de CLS contre Bibliothèque_A ainsi, en particulier parce que « Ploeh. * » Est maintenant « portée » pour la règle CLS 5 « Tous les noms introduits dans un champ d'application conforme CLS doit être indépendant distinct de nature ».

Modification soit l'espace de noms Class1InLibraryB ou Class1InLibraryC afin qu'ils deviennent distincts semble convaincre le compilateur il n'y a aucune chance pour un conflit de nom plus.

Si vous choisissez l'option (2), ajouter la référence et la compilation, vous verrez que la référence n'est pas réellement marquée dans l'ensemble obtenu méta-données, c'est donc une dépendance à temps la vérification compilation / seulement.

Autres conseils

Rappelez-vous que la CLS est un ensemble de règles applicables aux assemblages générés et est conçu pour soutenir l'interopérabilité entre les langues. Dans un sens, il définit le plus petit sous-ensemble commun de règles qu'un type doit suivre pour vous assurer qu'il est le langage et la plate-forme agnostique. CLS-conformité est également valable uniquement aux éléments qui sont visibles à l'extérieur de leur assemblage définir.

En regardant certaines des lignes directrices du code conforme CLS devrait suivre:

  • Évitez l'utilisation des noms couramment utilisés comme mots clés dans les langages de programmation.
  • vous attendez pas à des utilisateurs du cadre de pouvoir à l'auteur des types imbriqués.
  • On suppose que les mises en œuvre de méthodes du même nom et la signature sur différentes interfaces sont indépendantes.

Les règles de détermination CLS-conformité sont:

  • Lorsqu'un ensemble ne porte pas un System.CLSCompliantAttribute explicite, il est supposé porter System.CLSCompliantAttribute (false).
  • Par défaut, un type hérite de l'attribut CLS-respect de ce type d'enceinte (pour les types imbriqués) ou acquiert le niveau de conformité attaché à son ensemble (pour les types de haut niveau).
  • Par défaut, les autres membres (méthodes, champs, propriétés et événements) héritent de la CLS-conformité de leur type.

Maintenant, pour autant que le compilateur est concerné, (CLS Règle 1), il doit être en mesure d'appliquer les règles de CLS-conformité à toute information qui seront exportés en dehors de l'Assemblée et considère un type à être conforme CLS si toutes ses parties accessibles au public (ces classes, les interfaces, les méthodes, des champs, des propriétés et des événements qui sont disponibles pour l'exécution de code dans un autre assemblage) soit

  • ont des signatures composées uniquement de types CLS conformes, ou
  • sont indiquées comme étant non conforme CLS.

Par règles CTS, un champ d'application est tout simplement un groupe / collection de noms et dans un champ un nom peut faire référence à plusieurs entités tant qu'ils sont de différents types (méthodes, champs, types imbriqués, propriétés, événements) ou ont différentes signatures. Une entité nommée a son nom dans exactement un champ afin afin d'identifier cette entrée à la fois une portée et un nom doit être appliqué. La portée qualifie le nom.

Étant donné que les types sont nommés, les noms des types sont également regroupés pour champs d'application. Pour bien identifier un type, le nom du type doit être qualifié par la portée. Les noms des types sont scope par l'assemblée qui contient la mise en œuvre de ce type.

Pour les oscilloscopes qui sont conformes CLS, tous les noms doivent être indépendants de nature distincte, sauf si les noms sont identiques et résolus par la surcharge. En d'autres termes, alors que le CTS permet un seul type d'utiliser le même nom pour un champ et une méthode, la CLS n'a pas (CLS Règle 5).

En allant un peu plus loin, un type de CLS conforme ne doit pas exiger la mise en œuvre des types compatibles non-CLS (CLS Règle 20) et doit également hériter d'un autre type CLS plainte (CLS Règle 23).

Un assemblage peut dépendre d'autres ensembles si les mises en œuvre dans le cadre d'une des ressources de référence d'assemblage dont la portée ou appartenant à un autre ensemble.

  • Toutes les références à d'autres assemblées sont résolus sous le contrôle du champ de montage actuel.
  • Il est toujours possible de déterminer quel assemblage portée d'une mise en oeuvre particulière est en cours d'exécution en. Toutes les demandes provenant de ce champ d'assemblage sont résolus par rapport à ce champ d'application.

Qu'est-ce que doit être en mesure de vérifier que tous parties publiques de ce type sont conformes CLS aussi tout cela signifie en fin de compte est que pour vérifier la conformité CLS-d'un type, le compilateur. Cela signifie qu'il doit veiller à ce que le nom est unique dans une portée, qu'il ne dépend pas de types compatibles non-CLS pour une partie de sa mise en œuvre et qu'il hérite d'autres types qui sont également conformes CLS. La seule façon pour elle de le faire est en examinant tous le culemblies que les références de type.

Rappelez-vous que l'étape de construction dans Visual Studio est essentiellement une interface graphique pour exécuter MSBuild, qui est en fin de compte rien de plus qu'un moyen scénarisé pour appeler le compilateur de ligne de commande C #. Pour que le compilateur de vérifier la conformité CLS d'un type, il doit connaître et être en mesure de trouver tous les ensembles de ce type de références (non le projet). Comme il est appelé par MSBuild et, finalement, Visual Studio, la seule façon pour Visual Studio (MSBuild) pour l'informer de ces assemblées est en les incluant comme références.

De toute évidence, étant donné que le compilateur est capable de comprendre qu'il est des références « manquantes » afin de vérifier la conformité CLS et compiler avec succès, il aurait été bien si elle aurait pu simplement inclure les références automatiquement en notre nom. Le problème est ici pour déterminer qui version de l'assemblée à inclure et que l'assemblage est sur le système de fichiers. En forçant le développeur de fournir cette information, le compilateur permet de garantir qu'il est donné les informations correctes. Cela a aussi l'effet secondaire de faire en sorte que tous les ensembles dépendants sont copiés dans les dossiers de Debug/bin ou Release/bin lors de la construction de sorte qu'ils sont dans le bon répertoire lorsque l'application est exécutée après qu'il a été compilé.

Le problème est résolu dans Roslyn, qui est disponible dans Visual Studio 14.
En Juillet 2014, le CTP actuel est disponible ici .
Voir ce rapport de bogue pour plus de détails.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top