7
votes

Conversion de type générale sans risque d'exception

Je travaille sur un contrôle qui peut prendre un certain nombre de types de données différents (tout ce qui implémente icomparable).

Je dois être capable de les comparer avec une autre variable passée.

si le Le type de données principal est une date de données et je suis passé une chaîne, j'ai besoin de

  • tentative de convertir la chaîne en une date d'heure pour effectuer une comparaison de date.
  • Si la chaîne ne peut pas être convertie en une date d'heure, faites une comparaison de chaîne.

    Donc, j'ai besoin d'un moyen général pour tenter de convertir de tout type à n'importe quel type. Assez facile, .NET nous fournit le TypeConverter classe .

    Maintenant, le meilleur que je puisse travailler à faire pour déterminer si la chaîne peut être convertie en une date d'heure pour utiliser des exceptions. Si le ConvertDrom soulève une exception, je sais que je ne peux pas faire la conversion et faire la comparaison des chaînes.

    Ce qui suit est le meilleur que j'ai obtenu: xxx

    une partie de nos normes à l'état de travail qui:

    Exceptions ne devrait être soulevé que lors d'une situation d'exception - c'est-à-dire. Une erreur est rencontrée.

    Mais ce n'est pas une situation exceptionnelle. J'ai besoin d'une autre solution autour de cela.

    La plupart des types de variable ont un Tryparse méthode qui retourne un booléen pour vous permettre de déterminer si la conversion a réussi ou non. Mais il n'y a pas de méthode de tryconvert disponible pour TypeConverter. CANConvertFrom uniquement Derminés s'il est possible de convertir entre ces types et ne considère pas les données réelles à convertir. Le La méthode ISVALID est également inutile.

    Idées?

    edit

    Je ne peux pas utiliser comme et est. Je ne connais pas les types de données à la compilation. Donc, je ne sais pas quoi de même et c'est à !!!

    edit

    OK cloué le bâtard. Ce n'est pas aussi bien rangé que Marc Gravells, mais ça marche (j'espère). Merci pour la pulvérisation Marc. Travaillera sur le ranger quand j'aurai le temps, mais j'ai une pile de bugs de bugs que je dois continuer avec. xxx


6 commentaires

Pas vraiment, la question sait que le type va être converti en. Ici je ne fais pas. La réponse à cette question ne m'aider pas du tout.


Ouf .. Je pensais que j'allais avoir la question fermée. Ive a passé des heures sur celui-ci .. ;-)


En ce qui concerne les normes telles que celles-ci, vous devez savoir que vous traitez également avec le code des autres peuples. D'autres personnes peuvent ne pas utiliser les mêmes normes. Ainsi, tandis que la norme prescrit que vous ne devez pas soulever une exception pour le flux de contrôle dans votre code, si le code écrit par une tierce partie ne vous permet pas de l'écrire facilement ou avec élégance sans attraper une exception, alors vous allez avoir à attraper une exception. Bien sûr, il pourrait y avoir une solution qui n'utilise pas d'exceptions, je voulais juste signaler cela s'il n'y avait pas.


Quel est le problème avec l'utilisation de DateTime.trypsarse dans cette instance? Était datetime juste un exemple spécifique?


@sapph oui, il peut être n'importe quel type.


Eh bien, vous pouvez faire une méthode tryconvert qui enveloppe la manipulation des exceptions ...


4 Réponses :


0
votes

Donc, j'ai besoin d'une manière générale pour tenter de convertir de tout type à n'importe quel type. Assez facile, .NET nous fournit le Classe Classe.

Vous demandez trop. xxx

devrais-je convertir un chat vers un chien chien ?

vous ' LL Trouver votre problème est beaucoup plus facile à résoudre si vous spécifiez plus précisément (de préférence exactement) ce que vous voulez que le comportement de la méthode soit. Donc, écrivez les entrées attendues et ce que vous voulez que la sortie soit dans chaque cas possible. Ensuite, votre méthode devrait se écrir.

Donc maintenant, nous avons cette spécification:

Si le type de données principal est un DateTime , et je suis passé une chaîne , j'ai besoin de

Essayez de convertir la chaîne sur un DateTime pour effectuer une date comparaison de la comparaison. Si la chaîne ne peut pas être convertie en un DateTime , faites une chaîne comparaison. xxx


3 commentaires

Je veux un Bool Typonverter.ecteurConvert (Object InObject, Out Object ConvertedObjected). Un peu comme DateTime.tryparse. Je veux faire exactement ce que l'échantillon de code que j'ai affiché est, mais sans l'exception étant soulevée. Je ne fais pas vraiment des objets ici, juste des types de variables de base: INTS, Strings, DateTimes .. Je pensais que ma question était assez claire.


@Pongus: Ce n'est pas clair. Quel type essayez-vous de convertir inobject à? Essayez-vous de convertir au type de convertidObjected (sic)?


mes excuses. C'est un contrôle de la grille. J'ai besoin de trier et de filtrer sur n'importe quel type de données qui est jeté sur moi aussi longtemps qu'il est icomparable.



4
votes

Je dirais que ce code devrait vraiment lancer des exceptions quand il ne peut pas comprendre une conversion. Si les deux arguments sont passés sont DateTime.now et Color.fuschsia , vous ne pouvez faire aucune comparaison significative entre elles, donc toute valeur que vous retournez serait fausse. C'est la définition du bon moment pour lancer une exception.

Si vous avez absolument besoin d'éviter des exceptions, il n'est pas possible de faire ce que vous voulez avec des types arbitraires. Chaque type a ses propres règles sur lesquelles il peut analyser les valeurs et le convertisseur n'a aucun moyen de le dire à l'avance. (C'est-à-dire que vous l'avez remarqué, il sait que vous pouvez parfois convertir une chaîne vers un DateTime , mais il n'est pas conçu pour savoir que "1 / 1/2010 "est un DateTime valide pendant que" Fred "n'est pas.)


2 commentaires

Dans cette situation, il est parfaitement valide pour que les entrées soient une date d'heure et une couleur. Évidemment comme leurs types de types bruts, ils ne peuvent pas être comparés. C'est pourquoi je veux vérifier si elles peuvent être converties de manière à ce qu'une comparaison utile puisse être faite. Je veux juste vérifier, je ne veux pas que cela soit une condition d'erreur.


Donc, ce que vous voulez, c'est juste une méthode pour vérifier si une conversion réussirait, sans faire la conversion? Ce n'est pas possible avec des types arbitraires. TypeConverter est conçu pour tenter la conversion et lancer des exceptions sur l'échec. Vous pouvez vérifier les types courants que vous savez comment gérer, comme DateTime et double etc., et appelez leur Tryparse méthodes. Mais cela ne fonctionne que pour les types que vous vérifiez.



5
votes

S'il n'est pas possible de l'écrire sans exceptions, vous pouvez isoler le code problématique en le refactant dans une méthode, comme: xxx

idéalement, vous devez passer à des types nullables comme paramètre de sortie, de sorte que NULL représente une valeur non définie (car elle ne pouvait pas faire une conversion) plutôt que la valeur par défaut (c.-à-d. 0 pour int)


0 commentaires

9
votes

sont des génériques une option? Voici un piratage effronté qui chasse la méthode Tryparse Code> et l'appelle via un délégué (mis en cache):

using System;
using System.Reflection;

static class Program
{
    static void Main()
    {
        int i; float f; decimal d;
        if (Test.TryParse("123", out i)) {
            Console.WriteLine(i);
        }
        if (Test.TryParse("123.45", out f)) {
            Console.WriteLine(f);
        }
        if (Test.TryParse("123.4567", out d)) {
            Console.WriteLine(d);
        }
    }
}
public static class Test
{
    public static bool TryParse<T>(string s, out T value) {
        return Cache<T>.TryParse(s, out value);
    }
    internal static class Cache<T> {
        public static bool TryParse(string s, out T value)
        {
            return func(s, out value);
        }    
        delegate bool TryPattern(string s, out T value);
        private static readonly TryPattern func;
        static Cache()
        {
            MethodInfo method = typeof(T).GetMethod(
                "TryParse", new Type[] { typeof(string), typeof(T).MakeByRefType() });
            if (method == null) {
                if (typeof(T) == typeof(string))
                    func = delegate(string x, out T y) { y = (T)(object)x; return true; };
                else
                    func = delegate(string x, out T y) { y = default(T); return false; };
            } else {
                func = (TryPattern) Delegate.CreateDelegate(typeof(TryPattern),method);
            }            
        }
    }
}


4 commentaires

Ouais, Wow, ça regarde juste le ticket! Merci. Devra juste attendre lundi pour l'essayer au travail. J'aime ça!


Bummer a refusé. La solution avait l'air bien, mais je ne suis que passer les données comme objets. Je ne connais pas les types au moment de la compilation. Je me rends compte que je n'ai pas très bien formulé ma question, d'où la confusion. Ceci est proche si, très proche, je peux toujours avoir une partie à l'aide de la partie réflexion de celui-ci, je suis sûr.


Woohoo! Je l'ai tordue un peu à propos de la solution. Voir la modification dans mon message. Merci beaucoup!


@Marcgravell je l'ai édité pour faire string.tryparse () non échoue, pouvez-vous vérifier (/ approuver l'édition) et y a-t-il une meilleure façon de faire (t) (objet) " chaîne "? Apparemment, Windows Phone 7 n'a pas Mise en œuvre TypeDeScriptor, est-ce aussi bon travail autour pour cela?