web-dev-qa-db-fra.com

Un espace de noms et une classe portant le même nom?

J'organise un projet de bibliothèque et j'ai une classe de gestionnaire central nommée Scenegraph ainsi que de nombreuses autres classes qui résident dans l'espace de noms Scenegraph.

Ce que j’aimerais vraiment, c’est que le scénégraphe soit MyLib.Scenegraph et les autres classes à être MyLib.Scenegraph.*, mais il semble que la seule façon de le faire serait de rendre toutes les autres classes des classes internes de Scenegraph dans le fichier Scenegraph.cs, ce qui est trop compliqué.

Au lieu de cela, je l'ai organisé comme Mylib.Scenegraph.Scenegraph et MyLib.Scenegraph.*, quelle sorte de travail mais je trouve que Visual Studio est confus sous certaines conditions quant à savoir si je fais référence à la classe ou à l’espace de noms.

Existe-t-il un bon moyen d’organiser ce package pour le rendre pratique pour les utilisateurs sans avoir à glaner tout mon code dans un fouillis impossible à maintenir?

82
user430788

Je ne vous recommande pas de nommer une classe comme son espace de noms, voir this .

Dans la section 3.4, les directives relatives à la conception du cadre "n'utilisez pas le même nom pour un espace de noms et un type dans cet espace de noms". C'est:

namespace MyContainers.List 
{ 
    public class List { … } 
}

Pourquoi cette méchanceté? Oh, laisse-moi compter les chemins.

Vous pouvez vous retrouver dans des situations où vous pensez faire référence à une chose alors qu'en réalité vous faites référence à autre chose. Supposons que vous vous retrouviez dans cette situation regrettable: vous écrivez Blah.DLL et importez Foo.DLL et Bar.DLL, qui, malheureusement, ont tous deux un type appelé Foo:

// Foo.DLL: 
namespace Foo { public class Foo { } }

// Bar.DLL: 
namespace Bar { public class Foo { } }

// Blah.DLL: 
namespace Blah  
{   
using Foo;   
using Bar;   
class C { Foo foo; } 
}

Le compilateur donne une erreur. “Foo” est ambigu entre Foo.Foo et Bar.Foo. Bummer. Je pense que je vais résoudre ce problème en qualifiant complètement le nom:

   class C { Foo.Foo foo; } 

Cela donne maintenant l'erreur d'ambiguïté " Foo dans Foo.Foo est ambigu entre Foo.Foo et Bar.Foo ". Nous ne savons toujours pas à quoi se réfère le premier Foo, et tant que nous ne pourrons pas comprendre cela, nous ne chercherons même pas à comprendre à quoi le deuxième fait référence.

98
pinckerman

Donner le même nom à l'espace de noms et à la classe peut perturber le compilateur, comme d'autres l'ont dit.

Comment l'appeler alors?

Si l'espace de noms comporte plusieurs classes, recherchez un nom définissant toutes ces classes.

Si le l'espace de noms n'a qu'une classe (et par conséquent la tentation de lui donner le même nom), nommez l'espace de noms Nom de la classe NS . Voici comment Microsoft nomme au moins leurs espaces de noms.

9
GoTo

Je suggérerais que vous suiviez le conseil que j'avais sur Microsoft.public.dotnet.languages.csharp D'utiliser MyLib.ScenegraphUtil.Scenegraph Et MyLib.ScenegraphUtil.*.

8
Ant_222

CA1724: Type Names Should Not Match Namespaces ...

Fondamentalement, si vous suivez l'analyse du code pour coder correctement, cette règle dit de ne pas faire ce que vous essayez de faire. Analyse de code est très utile en vous aidant à trouver potentiel problèmes.

5
m-y

Juste en ajoutant mes 2 centimes:

J'ai eu la classe suivante:

namespace Foo {
    public struct Bar {
    }
    public class Foo {
        //no method or member named "Bar"
    }
}

Le client a été écrit comme ceci:

using Foo;

public class Blah {
    public void GetFoo( out Foo.Bar[] barArray ) {
    }
}

En oubliant l'erreur GetFoo ne renvoyant pas la sortie au lieu d'utiliser le paramètre out, le compilateur n'a pas pu résoudre le type de données Foo.Bar []. Il renvoyait l'erreur: impossible de trouver le type ou l'espace de nom Foo.Bar.

Il semble que, lorsqu'il a essayé de le compiler, il ait résolu Foo en tant que classe et n'a pas trouvé de classe incorporée Bar dans la classe Foo. Il n'a également pas pu trouver un espace de noms appelé Foo.Bar. La recherche d'une classe Bar dans l'espace de noms Foo a échoué. Les points dans un espace de noms ne sont PAS syntaxiques. La chaîne entière est un jeton, pas les mots délimités par les points.

Ce comportement a été présenté par VS 2015 sous .Net 4.6.

4
Steve

Ancien post, mais j'y vais avec une autre idée qui pourrait aider quelqu'un:

"... mais il semble que la seule façon de le faire serait de faire en sorte que toutes les autres classes soient des classes internes de Scenegraph dans le fichier Scenegraph.cs, ce qui est trop compliqué."

C'est vraiment la meilleure implémentation pour un tas de scénarios. Mais je suis d’accord pour dire qu’avoir tout ce code sur le même fichier .cs est ennuyant (pour le moins).

Vous pouvez le résoudre en faisant de la classe de base une "classe partielle", puis continuez à créer les classes internes sur leurs propres fichiers (rappelez-vous qu’elles devront déclarer le complément de classe de base, puis passer à la classe interne spécifique. pour ce fichier).

Quelque chose comme...

Scenegraph.cs:

namespace MyLib
{
    public partial class Scenegraph
    {
        //Scenegraph specific implementations
    }
}

DependentClass.cs:

namespace MyLib
{
    public partial class Scenegraph
    {
        public class DependentClass
        {
            //DependentClass specific implementations
        }
    }
}

Je pense que c’est le plus près possible d’une implémentation propre des classes internes sans avoir à tout encombrer à l’intérieur d’un seul fichier énorme et désordonné.

0
Marcelo Myara

Comme d'autres l'ont déjà dit, il est recommandé d'éviter de nommer une classe comme son espace de noms.

Voici quelques suggestions de dénomination supplémentaires de ne réponse par svick à une question connexe "Même nom de classe et de même nom" sur le logiciel. Ingénierie Stack Exchange:

Vous avez raison de ne pas nommer l’espace de nom de la même manière qu’un type. Je pense qu'il y a plusieurs approches que vous pouvez utiliser:

  • Pluraliser: Model.DataSources.DataSource

Cela fonctionne particulièrement bien si l'objectif principal de l'espace de noms est de contenir des types hérités du même type de base ou d'implémenter la même interface.

  • Raccourcissez: Model.QueryStorage

Si un espace de noms ne contient qu'un petit nombre de types, vous n'avez peut-être pas besoin de cet espace de noms du tout.

  • Rendre entreprise: Model.ProjectSystem.Project

Cela peut fonctionner spécialement pour les fonctionnalités qui constituent une partie importante de votre produit. Elles méritent donc leur propre nom.

(Notez que la réponse ci-dessus utilise Model.DataSource.DataSource, Model.QueryStorage.QueryStorage., et Model.Project.Project comme exemples plutôt que MyLib.Scenegraph.Scenegraph.)

(J'ai également trouvé les autres suggestions de nommage dans les autres réponses utiles.)

0
sonny