donné un type générique La question se pose d'un code réel. Je souhaite unifier l'accès aux paramètres passés via la chaîne de requête dans mon application ASP.NET. Et je souhaite spécifier une valeur par défaut du même type, mais assurez-vous que actuellement je suis forcé ayant deux surcharges du Ça fonctionne bien, mais je me demande s'il est possible de fusionner les deux fonctions comme celle-ci. p> en C ++, j'utiliserais des traits de type, tels que t code> in c #, je me demande comment acquérir le type
q code>, qui est égal à
t? code> pour non-nullable
t code> et
t code> pour déjà nullable
t code>.
null code> peut être transmis comme une valeur par défaut. P>
fetchvalue code> - une sans valeur par défaut et une avec elle: p>
PROMOCULLULLABLABLE
PROMOTELLULLABLE CODE > Pour des types nullables et non nullables. Mais qu'en est-il de C #? P> P>
6 Réponses :
Essayez ce qui suit:
var val = FetchValue<NullableString>("blah", new NullableString() { Value = "default" });
Je veux que cette fonction fonctionne avec des types nullables, du moins avec des chaînes.
Cela obtient un code sur le site de l'appelant, donc je ne pense pas que ce soit pratique. Belle pensée à envelopper string code> dans
struct code> cependant.
@Mikhail Je suppose que vous pourriez avoir les appels à cette fonction proxé, donc en cas de transmission d'un type de chaîne, cela concernera dans cette structure. Mais je suis d'accord, ça va commencer à devenir très désordonné à partir de là.
ne répond pas directement à la question posée, mais j'écrirais ceci: de sorte que la majeure partie du code n'existe qu'une seule fois - et vous pouvez même en réalité avoir l'appel code choisissez d'avoir Même si vous pouviez créer la déclaration de paramètre que vous vouliez, cette ligne serait toujours un problème : p> s'il s'est avéré que null code> comme une valeur par défaut, s'il le choisit. p>
par défaut_value code> était un
t? code> plutôt qu'un
t code >, alors le code ci-dessus ne fonctionne pas. Même si vous faites un casting: p>
return (T)default_value;
C'est presque comment il est actuellement mis en œuvre :)
Ok, je n'ai pas reçu de réponse à ma question, mais j'ai une explication pourquoi il n'y a pas de réponse. Merci, j'accepte cela.
Vous pouvez spécifier la contrainte Classe em> pour vous assurer que les appelants passent dans un type de référence (qui est nullable): Dans ce cas, vous déléguez la responsabilité de casting t à t? Si nécessaire à l'appelant, qui est gentil de toute façon: il peut savoir mieux! p> p>
Identique à ce que @terric - je veux vraiment des types nullables et non nullables (structs de classe AS) autorisés. Au moins int code> s et
chaîne code> s.
Étant donné que votre type de retour est Essayez celui-ci, il vous permet de passer un type de valeur nullable ( t code> et
t code> Beeing a un type de valeur, il ne peut pas être null.
Donc, vous devrez toujours passer un type nullable, car vous voulez un retour nul, non?
i code>) et une normale Type de référence (
O CODE>): P>
static void Main(string[] args)
{
int? i = 5;
object x = new object();
object o = FetchValue("x", i);
o = FetchValue("x", x);
}
private static T? FetchValue<T>(string name, T? p) where T : struct
{
T? result = (T?)FetchValue(name, (object)p);
return result;
}
private static T FetchValue<T>(string name,
T default_value = default (T)) // default(T) where T is a reference type will always be null!
where T : class
{
// do whatever you want
var page = HttpContext.Current.Handler as Page;
string str = page.Request.QueryString[name];
if (str == null)
{
if (default_value == null)
{
throw new HttpRequestValidationException("A " + name + " must be specified.");
}
else
{
return default_value;
}
}
return (T)Convert.ChangeType(str, typeof(T));
}
Dans ce cas, je ne peux pas utiliser fetchvalue
null code> retour, je veux une valeur par défaut ou une exception.
Lorsque vous utilisez fetchvalue
int code> n'est pas un type de référence. Lorsque vous parlez de
default_value code> je vous ai appris que vous voulez toujours une référence / nullable type de retour. (Qu'en est-il de bien sûr ne pas très malheur, car vous utiliseriez
objet code> comme type de retour alors)
Vous pouvez faire ce que vous voulez en cette manière simple:
public static T FetchValue<T>(string name, T defaultValue = null) where T : class { } public static T? FetchValue<T>(string name, T? defaultValue = null) where T : struct { }
Cela nécessite deux surcharges, alors que j'ai déjà une solution avec deux surcharges, ce que je trouve plus facile.
@Mikhail C'est la voie la plus simple et la plus efficace.
Il y a mon exemple:
Belle pensée à faire une fonction d'extension. Mais le fetchvalue code> n'est pas de type sécurisé, par ex. On peut appeler
fetchvalue
De plus, je ne comprends pas pourquoi fetchvalue code> et
fetchvaluefromCurrentPage code> n'a pas de prototypes symétriques. Il est impossible d'utiliser des structures sans valeurs par défaut pour ce dernier, comme celui-ci:
pageeextensions.fetchvaluefromcurrentPage
Je pense que vous avez besoin de quelque chose comme 'renvoyer défaut (t)' dans le cas de T est valuetype. Et dans votre exemple: la valeur null ne peut pas être une valeur par défaut - ce n'est pas une bonne pratique. Je veux renvoyer la valeur nulle comme valeur par défaut par exemple.
Personnellement, je pense que le code est plus clair du site d'appel si vous avez simplement deux surcharges.
@Matthewwatson Le code du site d'appel est exactement le même i> pour les deux implémentations.
Le compilateur lutterait pour générer un code approprié pour
retourfild_value; code> si
par défaut_value code> était-ce "peut-être un
t code>, peut-être un
t? < / code> "type. Même
retour (t) par défaut_value; code> nécessite un code différent s'il s'agit d'un
t? Code>. N'oubliez pas que le compilateur doit générer un seul code qui convient à toutes les instanciations.
@Damien_the_unbeliever Que voulez-vous dire que le code généré serait le même pour différentes instanciations? .. ce n'est pas vrai pour les modèles C ++. Est-ce vrai pour C # Generics?
Les génériques C # sont une fonction d'exécution, et non une fonction de compilation de la compilation que dans les modèles de C ++. En tant que tel, le compilateur doit générer une séquence une i> d'IL qui sera valide pour tout paramètre de type fourni. (Il existe une certaine variation dans la manière dont l'IL est traduite en code de machine à JIT Time, en fonction des types de valeur / de référence, mais l'IL est toujours identique)
À titre de note de côté - j'irais probablement avec les deux surcharges, mais j'ai probablement une méthode interne privée
Bool TryFetStetvalue (nom de chaîne, valeur REF T) code> que les deux appellent. Il fait le travail sale, puis tous les méthodes code> fetchvalue code> sont soit renvoyer la valeur par défaut, soit lancer une exception (selon la surcharge qu'ils sont).
@Damien_the_unbeliever Je ne le savais pas, merci. Concernant
tryfetchvalue code> - Voici comment je l'ai réellement mis en œuvre :)