Caractéristiques cachées de C#? [fermé]

cela m'est venu à l'esprit après que j'ai appris ce qui suit de cette question :

where T : struct

nous, développeurs C#, tous connaissent les bases de C#. Je veux dire déclarations, instructions conditionnelles, boucles, opérateurs, etc.

certains d'entre nous ont même maîtrisé les choses comme génériques , types anonymes , lambdas , LINQ , ...

mais quelles sont les caractéristiques ou les astuces les plus cachées de C# que même les fans de C#, les toxicomanes, les experts connaissent à peine?

Voici les traits révélés jusqu'à présent:



mots clés

attributs

syntaxe

Caractéristiques Linguistiques

Visual Studio Features

Cadre

méthodes et propriétés

Trucs Et Astuces

  • Belle méthode pour les gestionnaires d'événements par Andreas H. R. Nilsson
  • Majuscule comparaisons par John
  • types d'accès anonymes sans réflexion par dp
  • Un moyen rapide paresseusement instancier les propriétés de collection par Sera
  • JavaScript comme anonyme inline-fonctions par roosteronacid

autres

1476
demandé sur Serhat Ozgel 2008-08-12 20:32:24

30 réponses

ce n'est pas C# per se, mais je n'ai vu personne qui utilise vraiment System.IO.Path.Combine() dans la mesure où ils devraient. En fait, toute la classe Path est vraiment utile, mais personne ne l'utilise!

je suis prêt à parier que chaque application de production a le code suivant, même si elle ne devrait pas:

string path = dir + "\" + fileName;
752
répondu ageektrapped 2008-08-13 01:53:50

lambdas et le type inferrence sont sous-estimés. Lambdas peut avoir plusieurs déclarations et ils double comme un objet délégué compatible automatiquement (assurez-vous juste que la signature correspondent) comme dans:

Console.CancelKeyPress +=
    (sender, e) => {
        Console.WriteLine("CTRL+C detected!\n");
        e.Cancel = true;
    };

notez que je n'ai pas de new CancellationEventHandler et je n'ai pas à spécifier les types de sender et e , ils sont infersibles de l'événement. C'est pourquoi c'est moins lourd à l'écriture de l'ensemble delegate (blah blah) qui exige également que vous spécifiez des types de paramètres.

Lambdas n'avez pas besoin renvoyer rien et l'inférence de type est extrêmement puissant dans le contexte de ce genre.

Et BTW, vous pouvez toujours revenir Lambdas qui font Lambdas dans la programmation fonctionnelle sens. Pour exemple, voici un lambda qui fait un lambda qui gère un Bouton.Cliquez sur l'événement:

Func<int, int, EventHandler> makeHandler =
    (dx, dy) => (sender, e) => {
        var btn = (Button) sender;
        btn.Top += dy;
        btn.Left += dx;
    };

btnUp.Click += makeHandler(0, -1);
btnDown.Click += makeHandler(0, 1);
btnLeft.Click += makeHandler(-1, 0);
btnRight.Click += makeHandler(1, 0);

Note la chaîne: (dx, dy) => (sender, e) =>

maintenant c'est pourquoi je suis heureux d'avoir pris la classe de programmation fonctionnelle: -)

mis à part les pointeurs en C, je pense que c'est l'autre chose fondamentale que vous devriez apprendre: -)

585
répondu chakrit 2012-02-13 21:53:50

From Rick Strahl :

vous pouvez enchaîner le ?? opérateur de sorte que vous pouvez faire un tas de nulle comparaisons.

string result = value1 ?? value2 ?? value3 ?? String.Empty;
528
répondu jfs 2008-08-27 01:34:54

génériques Alias:

using ASimpleName = Dictionary<string, Dictionary<string, List<string>>>;

il vous permet d'utiliser ASimpleName , au lieu de Dictionary<string, Dictionary<string, List<string>>> .

utilisez-le quand vous utiliseriez la même chose générique de grand long complexe dans beaucoup d'endroits.

455
répondu BlackTigerX 2009-09-12 20:32:44

From CLR via c# :

lors de la normalisation des cordes, il est très recommandé que vous utilisez ToUpperInvariant au lieu de Toowerinvariant parce que Microsoft a optimisé le code pour effectuer comparaisons en majuscules .

je me souviens d'une fois où mon collègue changeait les cordes en majuscules avant de comparer. Je me suis toujours demandé pourquoi il ne le fait qu' parce que je pense que c'est plus "naturel" de se convertir en minuscules d'abord. Après avoir lu le livre, je sais pourquoi.

438
répondu jfs 2008-08-15 11:06:48

mon truc préféré est d'utiliser l'opérateur null coalesce et les parenthèses pour instancier automatiquement les collections pour moi.

private IList<Foo> _foo;

public IList<Foo> ListOfFoo 
    { get { return _foo ?? (_foo = new List<Foo>()); } }
409
répondu Will 2010-03-21 17:14:24

éviter de vérifier la présence de manipulateurs d'événements nuls

Ajouter un délégué vide aux événements à declaration, supprimer la nécessité de toujours vérifier l'événement pour null avant de l'appeler il est génial. Exemple:

public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click = delegate {}; // add empty delegate!

Laissez-vous faire

public void DoSomething()
{
    Click(this, "foo");
}

au lieu de

public void DoSomething()
{
    // Unnecessary!
    MyClickHandler click = Click;
    if (click != null) // Unnecessary! 
    {
        click(this, "foo");
    }
}

s'il vous Plaît voir aussi cette discussion et de cette blog post par Eric Lippert sur ce sujet (et d'éventuels inconvénients).

314
répondu andnil 2017-05-23 11:55:01

tout le reste, plus

1) génériques implicites (Pourquoi seulement sur les méthodes et pas sur les classes?)

void GenericMethod<T>( T input ) { ... }

//Infer type, so
GenericMethod<int>(23); //You don't need the <>.
GenericMethod(23);      //Is enough.

2) lambdas simple avec un paramètre:

x => x.ToString() //simplify so many calls

3) types anonymes et initialisateurs:

//Duck-typed: works with any .Add method.
var colours = new Dictionary<string, string> {
    { "red", "#ff0000" },
    { "green", "#00ff00" },
    { "blue", "#0000ff" }
};

int[] arrayOfInt = { 1, 2, 3, 4, 5 };

un Autre:

4) les propriétés Auto peuvent avoir des portées différentes:

public int MyId { get; private set; }

Merci @szycoman de me le rappeler:

5) alias D'espace de noms (non pas que vous ayez besoin de cette distinction particulière):

using web = System.Web.UI.WebControls;
using win = System.Windows.Forms;

web::Control aWebControl = new web::Control();
win::Control aFormControl = new win::Control();
305
répondu Keith 2012-02-13 21:56:02

Je ne connaissais pas le mot-clé" as " depuis longtemps.

MyClass myObject = (MyClass) obj;

vs

MyClass myObject = obj as MyClass;

le second retournera null si obj n'est pas un MyClass, plutôt que jeter une exception de cast de classe.

286
répondu Mike Stone 2008-08-12 16:42:04

deux choses que j'aime sont des propriétés automatiques pour que vous puissiez réduire encore plus votre code:

private string _name;
public string Name
{
    get
    {
        return _name;
    }
    set
    {
        _name = value;
    }
}

devient

public string Name { get; set;}

aussi initialisateurs d'objets:

Employee emp = new Employee();
emp.Name = "John Smith";
emp.StartDate = DateTime.Now();

devient

Employee emp = new Employee {Name="John Smith", StartDate=DateTime.Now()}
262
répondu lomaxx 2008-08-13 07:39:13

le mot clé par défaut dans les types génériques:

T t = default(T);

se traduit par un 'null' si T est un type de référence, et 0 si c'est un int, false si c'est un booléen, etcetera.

255
répondu Eric Minkes 2008-08-13 10:20:07

Attributs en général, mais la plupart de tous DebuggerDisplay . Vous permet d'économiser ans.

226
répondu boj 2009-04-26 16:34:20

le @ dit au compilateur d'ignorer toute échapper les caractères dans une chaîne.

voulait juste clarifier celui-ci... il ne lui dit pas d'ignorer les caractères d'échappement, il dit en fait au compilateur d'interpréter la chaîne comme un littéral.

si vous avez

string s = @"cat
             dog
             fish"

il s'imprimera effectivement comme (notez qu'il inclut même l'espace utilisé pour l'indentation):

cat
             dog
             fish
221
répondu lomaxx 2009-09-12 20:33:53

je pense que l'une des caractéristiques les moins appréciées et les moins connues de C# (.NET 3.5) sont arbres D'Expression , surtout lorsqu'ils sont combinés avec des génériques et des Lambdas. C'est une approche de création D'API que les nouvelles bibliothèques comme NInject et Moq utilisent.

par exemple, disons que je veux enregistrer une méthode avec une API et que L'API doit obtenir le nom de la méthode

compte tenu de cette classe:

public class MyClass
{
     public void SomeMethod() { /* Do Something */ }
}

avant, il était très courant de voir les développeurs faire cela avec des chaînes et des types (ou quelque chose d'autre largement basé sur les chaînes de caractères):

RegisterMethod(typeof(MyClass), "SomeMethod");

ça craint à cause du manque de frappe forte. Et si je rebaptisais "SomeMethod"? Maintenant, en 3.5 cependant, je peux le faire d'une manière fortement typée:

RegisterMethod<MyClass>(cl => cl.SomeMethod());

dans laquelle la classe RegisterMethod utilise Expression<Action<T>> comme ceci:

void RegisterMethod<T>(Expression<Action<T>> action) where T : class
{
    var expression = (action.Body as MethodCallExpression);

    if (expression != null)
    {
        // TODO: Register method
        Console.WriteLine(expression.Method.Name);
    }
}

C'est une grande raison pour laquelle je suis amoureux des Lambdas et des arbres D'Expression en ce moment.

220
répondu Jason Olson 2010-06-06 20:22:32

" "151910920 le" rendement " venait à mon esprit. Certains des attributs comme [DefaultValue ()] sont aussi parmi mes favoris.

le " var "mot-clé est un peu plus connu, mais que vous pouvez l'utiliser dans les applications .NET 2.0 ainsi (aussi longtemps que vous utilisez le compilateur .NET 3.5 et mettez-le au code de sortie 2.0) ne semble pas être très bien connu.

Edit: kokos, merci pour l' ?? l'opérateur, qui est en effet très utile. Comme il est un peu difficile de google pour elle (comme ?? est tout simplement ignoré), voici la page de documentation MSDN pour cet opérateur: ?? Opérateur (Référence C)

209
répondu Michael Stum 2011-05-23 11:18:11

j'ai tendance à trouver que la plupart des développeurs C# ne connaissent pas les types 'nullables'. Fondamentalement, les primitives qui peuvent avoir une valeur nulle.

double? num1 = null; 
double num2 = num1 ?? -100;

définit un double nul, num1 , à nul, puis fixe un double régulier, num2 , à num1 ou -100 si num1 était nul.

http://msdn.microsoft.com/en-us/library/1t3y8s4s (VS.80).aspx

une chose de plus sur le type Nullable:

DateTime? tmp = new DateTime();
tmp = null;
return tmp.ToString();

C'est Chaîne de retour.Vide. Cochez cette lien pour plus de détails

198
répondu Brad Barker 2017-05-23 10:31:39

voici quelques caractéristiques cachées intéressantes de C#, sous la forme de mots clés non documentés de C#:

__makeref

__reftype

__refvalue

__arglist

ce sont des mots clés C# non documentés (même Visual Studio les reconnaît!) qui ont été ajoutés pour une boxe/unboxing plus efficace avant les génériques. Ils travaillent en coordination avec le Système.Typedreference struct.

il y a aussi _ _ arglist, qui est utilisé pour les listes de paramètres de longueur variable.

une chose les gens ne savent pas grand chose sur le système .Weakref -- une classe très utile qui garde la trace d'un objet mais permet tout de même au collecteur de déchets de le ramasser.

la caractéristique" cachée " la plus utile serait le mot-clé rendement. Ce n'est pas vraiment caché, mais beaucoup de gens ne le savent pas. LINQ est construit dessus; il permet des requêtes exécutées en retard en générant une machine d'état sous le capot. Raymond Chen a récemment publié un article sur en interne, à des détails insignifiants .

193
répondu Judah Himango 2011-11-10 17:14:12

les Syndicats (le C++ de la mémoire partagée type) dans le plus pur, coffre-fort, C#

sans recourir au mode et aux pointeurs dangereux, vous pouvez demander aux membres de la classe de partager de l'espace mémoire dans une classe/struct. Étant donné la classe suivante:

[StructLayout(LayoutKind.Explicit)]
public class A
{
    [FieldOffset(0)]
    public byte One;

    [FieldOffset(1)]
    public byte Two;

    [FieldOffset(2)]
    public byte Three;

    [FieldOffset(3)]
    public byte Four;

    [FieldOffset(0)]
    public int Int32;
}

vous pouvez modifier les valeurs des champs byte en manipulant le champ Int32 et vice-versa. Par exemple, ce programme:

    static void Main(string[] args)
    {
        A a = new A { Int32 = int.MaxValue };

        Console.WriteLine(a.Int32);
        Console.WriteLine("{0:X} {1:X} {2:X} {3:X}", a.One, a.Two, a.Three, a.Four);

        a.Four = 0;
        a.Three = 0;
        Console.WriteLine(a.Int32);
    }

produit ceci:

2147483647
FF FF FF 7F
65535

il suffit d'ajouter en utilisant le Système.Runtime.InteropServices;

185
répondu ZeroBugBounce 2008-09-23 20:39:01

utilisant @ pour les noms de variables qui sont des mots-clés.

var @object = new object();
var @string = "";
var @if = IpsoFacto(); 
176
répondu Mark Cidade 2008-08-18 01:45:02

si vous voulez quitter votre programme sans appeler de blocs ou de finaliseurs enfin utiliser FailFast :

Environment.FailFast()
168
répondu Jan Bannister 2009-12-19 03:06:41

retourner des types anonymes d'une méthode et accéder à des membres sans réflexion.

// Useful? probably not.
private void foo()
{
    var user = AnonCast(GetUserTuple(), new { Name = default(string), Badges = default(int) });
    Console.WriteLine("Name: {0} Badges: {1}", user.Name, user.Badges);
}

object GetUserTuple()
{
    return new { Name = "dp", Badges = 5 };
}    

// Using the magic of Type Inference...
static T AnonCast<T>(object obj, T t)
{
   return (T) obj;
}
153
répondu denis phillips 2011-04-06 13:39:36

En voici un utile pour les expressions régulières et les chemins de fichier:

"c:\program files\oldway"
@"c:\program file\newway"

le @ dit au compilateur d'ignorer tous les caractères échappés dans une chaîne de caractères.

146
répondu Patrick 2008-08-12 19:01:09

Mixins. Fondamentalement, si vous voulez ajouter une fonctionnalité à plusieurs classes, mais ne pouvez pas utiliser une classe de base pour toutes, demandez à chaque classe d'implémenter une interface (sans membres). Ensuite, écrivez une méthode d'extension pour l'interface , i.e.

public static DeepCopy(this IPrototype p) { ... }

bien sûr, une certaine clarté est sacrifiée. Mais ça fonctionne!

142
répondu Dmitri Nesteruk 2011-04-22 19:36:43

je ne sais Pas pourquoi quelqu'un voudrait utiliser Nullable, cependant. :- )

Vrai, Faux, FileNotFound ?

131
répondu Michael Stum 2008-11-22 07:39:07

celui-ci n'est pas "caché" d'autant que c'est mal nommée.

beaucoup d'attention est accordée aux algorithmes" map"," reduce", et"filter". Ce que la plupart des gens ne réalisent pas, C'est que .NET 3.5 a ajouté ces trois algorithmes, mais il leur a donné des noms très SQL-ish, basés sur le fait qu'ils font partie de LINQ.

"map" => Sélectionnez

Transforme les données d'une forme à une autre

"réduire" => Agrégation

Agrégats valeurs en un seul résultat

"filtre" = >

Filtres de données basé sur un critère

la capacité D'utiliser LINQ pour faire du travail en ligne sur des collections qui prenaient l'itération et des conditionnels peut être incroyablement précieux. Il est intéressant d'apprendre comment toutes les méthodes D'extension LINQ peuvent aider à rendre votre code beaucoup plus compact et maintenable.

117
répondu Brad Wilson 2008-08-16 23:55:28
Environment.NewLine

pour les nouvelles lignes indépendantes du système.

115
répondu nt. 2009-09-27 19:25:06

Si vous essayez d'utiliser des accolades à l'intérieur d'une Chaîne.Expression de Format...

int foo = 3;
string bar = "blind mice";
String.Format("{{I am in brackets!}} {0} {1}", foo, bar);
//Outputs "{I am in brackets!} 3 blind mice"
111
répondu Portman 2010-05-19 14:43:18
  1. ?? - opérateur de coalescence
  2. using ( statement / directive ) - grand mot-clé qui peut être utilisé pour plus que simplement l'appel Dispose
  3. readonly - devrait être utilisé plus
  4. netmodules-dommage qu'il N'y ait pas de support dans Visual Studio
104
répondu Doctor Jones 2010-04-30 10:31:14

@Ed, je suis un peu réticent à poster ceci, car c'est un peu plus que des Nippes. Cependant, je voudrais souligner que dans votre exemple de code:

MyClass c;
  if (obj is MyClass)
    c = obj as MyClass

si vous allez utiliser "est", pourquoi le suivre avec un cast sûr en utilisant "as"? Si vous avez vérifié que obj est en effet MyClass, une distribution standard de bog:

c = (MyClass)obj

... ne va jamais échouer.

de même, vous pourriez juste dire:

MyClass c = obj as MyClass;
if(c != null)
{
   ...
}

Je n'en sais pas assez sur les entrailles de .NET pour être sûr, mais mon instinct me dit que cela réduirait un maximum de deux opérations de jet type à un maximum d'un. Il est peu probable de casser la Banque de traitement de toute façon; personnellement, je pense que la dernière forme semble plus propre aussi.

103
répondu Dogmang 2008-08-12 18:03:12

peut-être pas une technique avancée, mais une que je vois tout le temps qui me rend fou:

if (x == 1)
{
   x = 2;
}
else
{
   x = 3;
}

peut être condensé en:

x = (x==1) ? 2 : 3;
98
répondu JasonS 2008-08-19 15:54:52