Créer une méthode générique en C #

J’essaie de combiner un tas de méthodes similaires dans une méthode générique. J’ai plusieurs méthodes qui renvoient la valeur d’une chaîne de requête, ou null si cette chaîne de requête n’existe pas ou n’est pas au bon format. Ce serait assez facile si tous les types étaient nativement nullables, mais je dois utiliser le type générique nullable pour les entiers et les dates.

Voici ce que j’ai maintenant. Cependant, il retournera un 0 si une valeur numérique n’est pas valide, ce qui est malheureusement une valeur valide dans mes scénarios. Quelqu’un peut-il m’aider? Merci!

public static T GetQuerySsortingng(ssortingng key) where T : IConvertible { T result = default(T); if (Ssortingng.IsNullOrEmpty(HttpContext.Current.Request.QuerySsortingng[key]) == false) { ssortingng value = HttpContext.Current.Request.QuerySsortingng[key]; try { result = (T)Convert.ChangeType(value, typeof(T)); } catch { //Could not convert. Pass back default value... result = default(T); } } return result; } 

Que faire si vous avez spécifié la valeur par défaut à renvoyer, au lieu d’utiliser la valeur par défaut (T)?

 public static T GetQuerySsortingng(ssortingng key, T defaultValue) {...} 

Cela facilite aussi les appels:

 var intValue = GetQuerySsortingng("intParm", Int32.MinValue); var strValue = GetQuerySsortingng("strParm", ""); var dtmValue = GetQuerySsortingng("dtmPatm", DateTime.Now); // eg use today's date if not specified 

L’inconvénient est que vous avez besoin de valeurs magiques pour indiquer des valeurs de chaîne de requête invalides / manquantes.

Je sais, je sais, mais …

 public static bool TryGetQuerySsortingng(ssortingng key, out T querySsortingng) 

Et ça? Modifiez le type de retour de T à Nullable

 public static Nullable GetQuerySsortingng(ssortingng key) where T : struct, IConvertible { T result = default(T); if (Ssortingng.IsNullOrEmpty(HttpContext.Current.Request.QuerySsortingng[key]) == false) { ssortingng value = HttpContext.Current.Request.QuerySsortingng[key]; try { result = (T)Convert.ChangeType(value, typeof(T)); } catch { //Could not convert. Pass back default value... result = default(T); } } return result; } 

Convert.ChangeType() ne gère pas correctement les types nullables ou les énumérations dans .NET 2.0 BCL (je pense qu’il est cependant corrigé pour BCL 4.0). Plutôt que de rendre l’implémentation externe plus complexe, faites en sorte que le convertisseur fasse plus de travail pour vous. Voici une implémentation que j’utilise:

 public static class Converter { public static T ConvertTo(object value) { return ConvertTo(value, default(T)); } public static T ConvertTo(object value, T defaultValue) { if (value == DBNull.Value) { return defaultValue; } return (T) ChangeType(value, typeof(T)); } public static object ChangeType(object value, Type conversionType) { if (conversionType == null) { throw new ArgumentNullException("conversionType"); } // if it's not a nullable type, just pass through the parameters to Convert.ChangeType if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { // null input returns null output regardless of base type if (value == null) { return null; } // it's a nullable type, and not null, which means it can be converted to its underlying type, // so overwrite the passed-in conversion type with this underlying type conversionType = Nullable.GetUnderlyingType(conversionType); } else if (conversionType.IsEnum) { // strings require Parse method if (value is string) { return Enum.Parse(conversionType, (string) value); } // primitive types can be instantiated using ToObject else if (value is int || value is uint || value is short || value is ushort || value is byte || value is sbyte || value is long || value is ulong) { return Enum.ToObject(conversionType, value); } else { throw new ArgumentException(String.Format("Value cannot be converted to {0} - current type is " + "not supported for enum conversions.", conversionType.FullName)); } } return Convert.ChangeType(value, conversionType); } } 

Ensuite, votre implémentation de GetQuerySsortingng peut être:

 public static T GetQuerySsortingng(ssortingng key) { T result = default(T); ssortingng value = HttpContext.Current.Request.QuerySsortingng[key]; if (!Ssortingng.IsNullOrEmpty(value)) { try { result = Converter.ConvertTo(value); } catch { //Could not convert. Pass back default value... result = default(T); } } return result; } 

Vous pouvez utiliser une sorte de monade par exemple (bien que je préfère la réponse de Jay)

 public class Maybe { private readonly T _value; public Maybe(T value) { _value = value; IsNothing = false; } public Maybe() { IsNothing = true; } public bool IsNothing { get; private set; } public T Value { get { if (IsNothing) { throw new InvalidOperationException("Value doesn't exist"); } return _value; } } public override bool Equals(object other) { if (IsNothing) { return (other == null); } if (other == null) { return false; } return _value.Equals(other); } public override int GetHashCode() { if (IsNothing) { return 0; } return _value.GetHashCode(); } public override ssortingng ToSsortingng() { if (IsNothing) { return ""; } return _value.ToSsortingng(); } public static implicit operator Maybe(T value) { return new Maybe(value); } public static explicit operator T(Maybe value) { return value.Value; } } 

Votre méthode ressemblerait à ceci:

  public static Maybe GetQuerySsortingng(ssortingng key) where T : IConvertible { if (Ssortingng.IsNullOrEmpty(HttpContext.Current.Request.QuerySsortingng[key]) == false) { ssortingng value = HttpContext.Current.Request.QuerySsortingng[key]; try { return (T)Convert.ChangeType(value, typeof(T)); } catch { //Could not convert. Pass back default value... return new Maybe(); } } return new Maybe(); } 

J’aime commencer par une classe comme celle-ci: parameters de la classe {public int X {get; set;} chaîne publique Y {get; ensemble; } // répète si nécessaire

  public settings() { this.X = defaultForX; this.Y = defaultForY; // repeat ... } public void Parse(Uri uri) { // parse values from query ssortingng. // if you need to distinguish from default vs. specified, add an appropriate property } 

Cela a bien fonctionné sur une centaine de projets. Vous pouvez utiliser l’une des nombreuses solutions d’parsing syntaxique pour parsingr les valeurs.