c# - Changer de casse sur le type c #





.net optimization switch-statement (5)


Le code suivant fonctionne plus ou moins comme on s'attendrait à un commutateur de type qui ne regarde que le type réel (par exemple, ce qui est retourné par GetType() ).

public static void TestTypeSwitch()
{
    var ts = new TypeSwitch()
        .Case((int x) => Console.WriteLine("int"))
        .Case((bool x) => Console.WriteLine("bool"))
        .Case((string x) => Console.WriteLine("string"));

    ts.Switch(42);     
    ts.Switch(false);  
    ts.Switch("hello"); 
}

Voici la machinerie nécessaire pour le faire fonctionner.

public class TypeSwitch
{
    Dictionary<Type, Action<object>> matches = new Dictionary<Type, Action<object>>();
    public TypeSwitch Case<T>(Action<T> action) { matches.Add(typeof(T), (x) => action((T)x)); return this; } 
    public void Switch(object x) { matches[x.GetType()](x); }
}

Dupliquer possible:
C # - Existe-t-il une meilleure alternative que celle de 'allumer le type'?

Bonjour supposons que je reçois un gros if / else sur le type de classe. c'est là un moyen de le faire avec un boîtier de commutateur?

Exemple :

function test(object obj)
{
if(obj is WebControl)
{

}else if(obj is TextBox)
{

}
else if(obj is ComboBox)
{

}

etc ...

Je voudrais créer quelque chose comme

switch(obj)
{
case is TextBox:
break;
case is ComboBox:
break;

}

}




Non.

http://blogs.msdn.com/b/peterhal/archive/2005/07/05/435760.aspx

Nous recevons beaucoup de requêtes pour les additions au langage C # et aujourd'hui je vais parler de l'une des plus courantes - allumer le type. Le type d'activation ressemble à une fonctionnalité très utile et directe: Ajoutez une construction de type commutateur qui active le type de l'expression plutôt que la valeur. Cela pourrait ressembler à ceci:

switch typeof(e) { 
        case int:    ... break; 
        case string: ... break; 
        case double: ... break; 
        default:     ... break; 
}

Ce type d'instruction serait extrêmement utile pour ajouter une méthode virtuelle telle qu'une répartition sur une hiérarchie de types disjoints, ou sur une hiérarchie de types contenant des types que vous ne possédez pas. Voyant un exemple comme celui-ci, vous pourriez facilement conclure que la fonctionnalité serait simple et utile. Cela pourrait même vous faire penser: «Pourquoi ces concepteurs de langage C # # * &% $ paresseux ne me facilitent-ils pas la vie et ajoutent-ils cette simple fonction de gain de temps?

Malheureusement, comme de nombreuses fonctionnalités de langage «simples», le changement de type n'est pas aussi simple qu'il apparaît. Les problèmes commencent lorsque vous regardez un exemple plus significatif, et non moins important, comme ceci:

class C {}
interface I {}
class D : C, I {}

switch typeof(e) {
case C: … break;
case I: … break;
default: … break;
}

Lien: https://blogs.msdn.microsoft.com/peterhal/2005/07/05/many-questions-switch-on-type/




La chose la plus simple à faire pourrait être d'utiliser la dynamique, c'est à dire que vous définissez les méthodes simples comme dans Yuval Peled réponse:

void Test(WebControl c)
{
...
}

void Test(ComboBox c)
{
...
}

Ensuite, vous ne pouvez pas appeler directement Test (obj), car la résolution de surcharge est effectuée au moment de la compilation. Vous devez affecter votre objet à une dynamique, puis appeler la méthode Test:

dynamic dynObj = obj;
Test(dynObj);



Voici une option qui reste aussi vrai que je pourrais faire à l'exigence de l'OP de pouvoir activer le type. Si vous plissez assez fort, cela ressemble presque à une véritable déclaration de changement.

Le code appelant ressemble à ceci:

var @switch = this.Switch(new []
{
    this.Case<WebControl>(x => { /* WebControl code here */ }),
    this.Case<TextBox>(x => { /* TextBox code here */ }),
    this.Case<ComboBox>(x => { /* ComboBox code here */ }),
});

@switch(obj);

Le x dans chaque lambda ci-dessus est fortement typé. Aucun casting requis.

Et pour faire ce travail magique, vous avez besoin de ces deux méthodes:

private Action<object> Switch(params Func<object, Action>[] tests)
{
    return o =>
    {
        var @case = tests
            .Select(f => f(o))
            .FirstOrDefault(a => a != null);

        if (@case != null)
        {
            @case();
        }
    };
}

private Func<object, Action> Case<T>(Action<T> action)
{
    return o => o is T ? (Action)(() => action((T)o)) : (Action)null;
}

Presque apporte des larmes à vos yeux, non?

Néanmoins, cela fonctionne. Prendre plaisir.




Wow, votre message a un tas de questions et de points. La plupart du raisonnement que vous obtenez de Microsoft est exactement sur le point. Commençons par tout sur List<T>

  • List<T> est hautement optimisée. Son utilisation principale est d'être utilisé comme membre privé d'un objet.
  • Microsoft ne l'a pas caché parce que parfois vous pourriez vouloir créer une classe qui a un nom plus convivial: class MyList<T, TX> : List<CustomObject<T, Something<TX>> { ... } . Maintenant, c'est aussi simple que de faire var list = new MyList<int, string>(); .
  • CA1002: N'exposez pas les listes génériques : En principe , même si vous envisagez d'utiliser cette application en tant que développeur unique, il est utile de développer de bonnes pratiques de codage, de sorte qu'elles vous inculquent à vous et une seconde nature. Vous êtes toujours autorisé à exposer la liste en tant que IList<T> si vous avez besoin d'un consommateur pour avoir une liste indexée. Cela vous permet de changer l'implémentation dans une classe plus tard.
  • Microsoft a rendu Collection<T> très générique parce que c'est un concept générique ... le nom dit tout; c'est juste une collection. Il existe des versions plus précises telles que SortedCollection<T> , ObservableCollection<T> , ReadOnlyCollection<T> , etc., qui implémentent chacune IList<T> mais pas List<T> .
  • Collection<T> permet de remplacer les membres (c.-à-d. Ajouter, Supprimer, etc.) car ils sont virtuels. List<T> ne l'est pas.
  • La dernière partie de votre question est sur place. Une équipe de football est plus que juste une liste de joueurs, donc ce devrait être une classe qui contient cette liste de joueurs. Pensez Composition vs Héritage . Une équipe de football a une liste de joueurs (une liste), ce n'est pas une liste de joueurs.

Si j'écrivais ce code, la classe ressemblerait probablement à ceci:

public class FootballTeam
{
    // Football team rosters are generally 53 total players.
    private readonly List<T> _roster = new List<T>(53);

    public IList<T> Roster
    {
        get { return _roster; }
    }

    // Yes. I used LINQ here. This is so I don't have to worry about
    // _roster.Length vs _roster.Count vs anything else.
    public int PlayerCount
    {
        get { return _roster.Count(); }
    }

    // Any additional members you want to expose/wrap.
}




c# .net optimization switch-statement