2010-06-23 3 views
1

J'ai une classe C# wraper avec une série de méthodes acceptant différents types de données:Déterminer à l'exécution si une distribution est autorisée (C#)

public class MyClass 
{ 
    public void ProcessString(string Value) { // implementation } 
    public void ProcessInt(int? Value) { // implementation }\ 
    public void ProcessOther(MyClass Value) { // implementation } 
} 

Je veux maintenant ajouter une méthode ProcessObject() générique pour éviter la nécessité de jeter explicitement un objet avant d'appeler une méthode de processus pertinent:

public void ProcessObject(object Value) 
{ 
    if (CanCastToString(Value) 
    { 
     ProcessString((string)Value); 
    } 
    else if (CanCastToInt(Value)) 
    { 
     ProcessInt((int?)Value); 
    } 
    // etc... 
} 

Le problème est que je ne sais pas ce que mes CanCastToInt méthodes devraient être - je besoin de ces méthodes pour pouvoir être robuste et faire face à des choses comme types nullable et autre ca défini par l'utilisateur sts

Comment est-ce que je peux faire ceci? Tout ce que je veux savoir est si un objet donné peut être jeté à un type donné, à savoir si oui ou non:

(SomeType)Value 

fonctionnera.

+2

Vous souciez-vous * représentation changeant * moulages? Autrement dit, supposons que vous avez un short dans votre objet. Voulez-vous être en mesure de le lancer à int? Vous ne pouvez pas lancer un short boxed directement à int; vous devez le lancer en int d'abord, puis à court.Vous pourriez vouloir lire mon essai sur le sujet pour vous assurer que vous comprenez ce qui se passe ici: http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx –

+0

Doivent-ils être des types de valeur encadrés? Normalement, la méthode OO consiste à créer une interface avec une méthode Process dont chaque type vous hérite, puis appelez la méthode sur l'objet sans vous soucier du type. –

Répondre

4

Il y a deux façons principales cela se fait habituellement:

if (Value is SomeType) 
{ 
    // Do something with a cast 
} 

ou

var v = Value as SomeType; 
if (v != null) 
{ 
    // Value was successfully cast as SomeType 
} 

Lorsque vous travaillez avec struct ou types intrinsèques, les rendre annulable:

var v = Value as int?; 
if (v != null) 
{ 
    ProcessInt(v.Value); 
} 
1

vous avez besoin de l'opérateur is. CanCastToString(x) ->x is string.

+0

Ne fonctionne pas - considère le cas où 'x' est un' Nullable ', et ensuite' x is int' renvoie false, mais '(int) x' fonctionne correctement. – Justin

+4

@Kragen: Êtes-vous * sûr * à ce sujet? Supposons que l'expression est de type à la compilation Nullable . Alors vous n'avez pas besoin de l'opérateur "is" parce que vous connaissez déjà le type exact de l'objet. Supposons que l'expression ne soit pas de type à la compilation Nullable . Quel type pourrait-il être? * Il doit être quelque chose en boîte *. Et il n'y a rien de tel qu'un intensible nullable en boîte! Un int nullable soit des boîtes à une référence nulle ou à un int boxed. (Un casse-tête pour vous: mon analyse n'est pas tout à fait correcte. Quel cas ai-je manqué?) –

-1
public void QuickTest() 
    { 
     object stringObj = "string"; 
     object nullableInt1 = (int?)null; 
     object nullableInt2 = (int?)1; 
     object decimalObj = 1.5m; 

     ProcessObject(stringObj); 
     ProcessObject(nullableInt1); 
     ProcessObject(nullableInt2); 
     ProcessObject(decimalObj); 
    } 

    public void ProcessObject(object value) 
    { 
     if (value == null) 
     { 
      Debug.WriteLine("null"); 
      return; 
     } 


     if (value is string) 
     { 
      Debug.WriteLine((string)value); 
      return; 
     } 

     string stringValue = value.ToString(); 

     int intTemp; 
     if (int.TryParse(stringValue, out intTemp)) 
     { 
      Debug.WriteLine(intTemp); 
      return; 
     } 

     decimal decimalTemp; 
     if (decimal.TryParse(stringValue, out decimalTemp)) 
     { 
      Debug.WriteLine(decimalTemp); 
      return; 
     } 
     // etc... 
    } 
1

Pourquoi ne pas exposer votre proc essing API directement, avec des surcharges pour différents paramètres?

public class MyClass 
{ 
    public void Process(string Value) { // implementation } 
    public void Process(int Value) { // implementation }\ 
    public void Process(MyClass Value) { // implementation } 
    public void Process(object Value) { // catch all method. Handle unknown entities, e.g. call ToString() } 
} 

EDIT Avec certains génériques magique vous pouvez avoir une seule méthode d'interface, un tas de méthodes d'assistance qui font le travail et une méthode fourre-tout où vous gérez les cas d'angle. De cette façon, vous évitez la boxe pour les types fondamentaux et vous avez une sécurité de type légèrement supérieure.

Pour votre méthode fourre-tout, vous pouvez essayer d'utiliser la méthode Type.IsAssignableFrom. Par exemple:

if (typeof(short).IsAssignableFrom(Value) 
    DoProcess((short)Value); 
if (typeof(byte).IsAssignableFrom(Value) 
    DoProcess((byte)Value); 

Je vous recommande de lire l'essai d'Eric Lippert sur les représentations. Heureusement, après cela, vous réaliserez qu'il pourrait être plus facile d'avoir une surcharge pour chaque type pris en charge. En outre, vous pourriez réaliser que le traitement des types de valeur Unboxing pourrait être une route vers l'enfer.

+0

J'ai déjà, mais je veux aussi exposer une méthode générique qui utilise des objets car cela rend les choses plus faciles ailleurs. – Justin

Questions connexes