86 votes

Défauts de conception C # (.NET)

Selon vous, quels sont les plus gros défauts de conception de C # ou du .NET Framework en général?

Mes favoris sont qu'il n'y a pas de type chaîne non nullable et que vous devez vérifier DBNull lors de l'extraction des valeurs d'un IDataReader.

73voto

Marc Gravell Points 482669
  • l' Reset() méthode IEnumerator<T> était une erreur (pour itérateur blocs, la langue spec même exigences que cela déclenche une exception)
  • la réflexion de méthodes qui retournent des tableaux ont été, dans Eric de vue, une erreur
  • la matrice de covariance a été et reste une bizarrerie; au moins en C# 4.0 / .NET 4.0, ce est fait correctement pour IEnumerable[<T>]
  • ApplicationException plutôt tombé hors de la faveur, - était-ce une erreur?
  • synchronisé collections - une belle idée, mais pas forcément utile dans la réalité: vous avez généralement besoin de synchroniser plusieurs opérations (Contains, alors Add), donc une collection qui synchronise les opérations distinctes n'est pas utile
  • de plus l'utilisation qui pourrait avoir été faite de l' using/lock modèle - peut-être leur permettant de partager une ré-utilisable (extensible?) la syntaxe; vous pouvez simuler cela en retournant IDisposable et à l'aide de using, mais il pourrait avoir été plus clair
  • itérateur blocs : pas de moyen simple de vérifier les arguments à l'avance (plutôt que paresseusement). Bien sûr, vous pouvez écrire enchaîné deux méthodes, mais c'est laid
  • plus simple immutabilité serait sympa; C# 4.0 aide un peu, mais pas assez de
  • pas de "ce ref-type de paramètre ne peut pas être null" soutien - bien que les contrats (4.0) de l'aide avec un peu cela. Mais une syntaxe comme celle - Foo(SqlConnection! connection) (qui injecte un null-contrôle / throw) serait bien (contrairement à int? etc)
  • le manque de soutien des opérateurs et des non-constructeurs par défaut avec les médicaments génériques, le C# 4.0 résout ce un peu avec dynamic, ou vous pouvez l'activer comme ceci


  • l'itérateur variable déclarée en dehors de la alors que dans l' foreach d'expansion, ce qui signifie que anon-méthodes/lambdas de capture de la seule variable, plutôt que par itération (douloureuse avec filetage/async/etc)

60voto

Quibblesome Points 14441

TextWriter est une classe de base de StreamWriter. wtf?

Cela déroute toujours mon enfer.

44voto

Scott Weinstein Points 11404

Les petits constructeurs peev - C # utilisent la syntaxe C ++ / Java selon laquelle le constructeur doit avoir le même nom que la classe.

New() ou ctor() aurait été bien meilleur.

Et bien sûr, des outils tels que coderush simplifient moins le changement de nom des classes, mais à partir d'un POV de lisibilité, New () offre une grande clarté.

39voto

naasking Points 1031

Je suis d'accord avec insistance à ce post (pour ceux poo-pooing le manque de ToString, il y a un débogueur attribut de fournir un format personnalisé pour votre classe).

Sur le haut de la liste ci-dessus, je voudrais également ajouter à la suite de demandes raisonnables:

  1. non nullable de référence types de comme un complément à nullable types de valeur,
  2. permet d'écraser une structure du constructeur vide,
  3. permettent de type générique contraintes de spécifier les classes scellées,
  4. Je suis d'accord avec un autre poster ici qui a demandé arbitraire constructeur signatures lorsqu'il est utilisé comme contraintes, c'est à dire. où T : nouveau(string), ou où T : nouveau(string, int),
  5. Je suis également d'accord avec une autre affiche ici à propos de la fixation des événements, à la fois pour vider les listes d'événements et dans la concurrente de réglage (même si ce dernier est délicat),
  6. les opérateurs devraient être définis comme des méthodes d'extension, et non pas comme des méthodes statiques de la classe (ou pas seulement en tant que méthodes statiques au moins),
  7. permettent de propriétés et de méthodes statiques pour les interfaces (Java a cela, mais C# ne fonctionne pas),
  8. permettre événement d'initialisation dans les initialiseurs d'objets (seuls les champs et les propriétés sont actuellement autorisées),
  9. pourquoi le "initialiseur d'objet" syntaxe utilisable uniquement lors de la création d'un objet? Pourquoi ne pas le rendre disponible à tout moment, c'est à dire. var e = new Foo(); e { Bar = baz };
  10. correction quadratique énumérable comportement,
  11. toutes les collections devraient avoir immuable instantanés pour l'itération (c'est à dire. la mutation de la collection ne devrait pas invalider l'itérateur),
  12. les tuples sont faciles à ajouter, mais efficace fermé algébrique de type "Soit" ne l'est pas, alors, j'aimerais une certaine façon de déclarer un fermé algébrique de type et d'appliquer exhaustive pattern matching (essentiellement soutien de première classe pour le modèle visiteur, mais beaucoup plus efficace); il suffit donc de prendre les énumérations, les étendre avec exhaustive correspondant à un modèle de soutien, et ne permettent pas invalide cas,
  13. J'aimerais soutien de filtrage en général, mais à tout le moins pour le type d'objet de tests; j'ai aussi un peu comme le commutateur de syntaxe proposé dans un autre post ici,
  14. Je suis d'accord avec un autre post que le Système.IO classes, comme Flux, sont assez mal conçu; une interface qui nécessite certaines implémentations de jeter NotSupportException est une mauvaise conception,
  15. IList devrait être beaucoup plus simple qu'elle ne l'est; en fait, cela peut être vrai pour de nombreux de béton les interfaces de collection, comme ICollection,
  16. de trop nombreuses méthodes de lancer des exceptions, comme IDictionary par exemple,
  17. Je préfère une forme de checked exceptions mieux que ce qui est disponible en Java (voir les recherches sur le genre et l'effet des systèmes de comment cela peut être fait),
  18. fixer différents ennuyeux coin des cas dans la méthode générique de résolution de surcharge; par exemple, essayez de fournir deux surcharge des méthodes d'extension, celui qui fonctionne sur les types de référence, et l'autre sur nullable struct types, et de voir comment votre inférence de type aime ça,
  19. fournir un moyen sécuritaire de se refléter sur le terrain et les noms des membres pour les interfaces de INotifyPropertyChanged, qui prennent le nom de champ comme une chaîne de caractères; vous pouvez le faire en utilisant une méthode d'extension qui prend un lambda avec un MemberExpression, c'est à dire. () => Foo, mais ce n'est pas très efficace,
  20. permettre aux opérateurs dans les interfaces, et de faire tous les types de numéro en œuvre IArithmetic; d'autres partagée de l'opérateur interfaces sont également possibles,
  21. de le rendre plus difficile à muter champs d'objet/propriétés, ou à tout le moins, de permettre l'annotation immuable champs et de faire le type de vérificateur de la faire respecter (juste le traiter comme de lecture-seule propriété fer chrissakes, c'est pas dur!); en fait, à unifier les champs et les propriétés de plus de bon sens car il n'y a aucun point en ayant à la fois; C# 3.0 automatique de propriétés sont une première étape dans cette direction, mais ils ne vont pas assez loin,
  22. simplifier déclarant constructeurs; j'aime F#'s approche, mais l'autre post ici qui nécessite simplement "nouveau" au lieu du nom de la classe est mieux au moins,

C'est assez pour le moment, je suppose. Ce sont tous des irritations que j'ai pu croiser au cours de la semaine écoulée. Je pourrais continuer pendant des heures si j'ai vraiment mis mon esprit à elle. C# 4.0 ajoute déjà nommé, les options et les arguments par défaut, j'ai catégoriquement qu'approuver.

Maintenant, pour une demande déraisonnable:

  1. ce serait vraiment bien si C#/CLR pourrait soutenir constructeur de type polymorphisme, c'est à dire. les génériques sur les génériques,

Jolie s'il vous plaît? :-)

29voto

tuinstoel Points 6329

Je ne comprends pas que tu ne peux pas faire

où T: nouveau (U)

Donc, vous déclarez que le type générique T a un constructeur autre que celui par défaut.

modifier:

Je veux faire ça:

 public class A 
{
    public A(string text) 
    {

    }
}


public class Gen<T> where T : new(string text) 
{

}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X