Maison  >  Article  >  développement back-end  >  Explication détaillée des paramètres facultatifs et exemples de paramètres nommés

Explication détaillée des paramètres facultatifs et exemples de paramètres nommés

零下一度
零下一度original
2017-06-24 09:46:312459parcourir

9.1 Paramètres facultatifs et paramètres nommés

    class Program
    {
        private static int s_n = 0;

        private static void M(int x = 9, string s = "A", DateTime dt = default(DateTime), Guid guid = new Guid())
        {
            Console.WriteLine("x={0},s={1},dt={2},guid={3}", x, s, dt, guid);
        }
        public static void Main()
        {
            //1.等同于M(9,"A",default(DateTime),new Guid());
            M();

            //2.等同于M(8,"X",default(DateTime),new Guid());
            M(8, "X");

            //3.等同于M(5,"A",DateTime.Now,Guid.NewGuid());
            M(5, guid: Guid.NewGuid(), dt: DateTime.Now);

            //4.等同于M(0,"1",default(DateTime),new Guid());
            M(s_n++, s_n++.ToString());

            //5.等同于以下两行代码:
            //string t1="2";int t2=3;
            //M(t2,t1,default(DateTime),new Guid());
            M(s: (s_n++).ToString(), x: s_n++);
        }
    }

9.1.1 Règles et principes

  • peuvent être des méthodes, des méthodes de constructeur et des paramètres de propriétés paramétrées (indexeur C#) spécifier les valeurs par défaut. Vous pouvez également spécifier des valeurs par défaut pour les paramètres qui font partie de la définition du délégué.

  • Les paramètres avec des valeurs par défaut doivent être placés après tous les paramètres sans valeurs par défaut. Mais il y a une exception : les paramètres tels que « tableau de paramètres » doivent être placés après tous les paramètres (y compris ceux avec des valeurs par défaut), et le tableau lui-même ne peut pas avoir de valeur par défaut.

  • La valeur par défaut doit être une valeur constante qui peut être déterminée au moment de la compilation (y compris les types primitifs, les types d'énumération et tout type de référence pouvant être défini sur null). Un paramètre d'un type valeur définit la valeur par défaut sur une instance du type valeur et fait en sorte que tous ses champs contiennent des valeurs nulles. Vous pouvez utiliser les mots-clés default ou new pour exprimer cette signification. Le code IL généré par les deux syntaxes est exactement le même.

  • Ne renommez pas les variables de paramètre, sinon tout appelant qui transmet les paramètres réels par nom de paramètre doit également modifier son code.

  • Changer la valeur par défaut d'un paramètre est potentiellement dangereux si la méthode est appelée depuis l'extérieur du module. Le site d'appel (où l'appel est effectué) intègre des valeurs par défaut dans ses appels. Si vous modifiez ultérieurement la valeur par défaut du paramètre, mais ne recompilez pas le code contenant le site d'appel, il transmettra l'ancienne valeur par défaut lors de l'appel de votre méthode. Envisagez d'utiliser la valeur par défaut 0/null comme valeur sentinelle pour indiquer le comportement par défaut. Exemple :

        //不要这样做:
        private static string MakePath(string filename = "Untitled")
        {
            return string.Format(@"c\{0}.txt", filename);
        }
    
        //而要这样做:
        private static string MakePath(string filename = null)
        {
            return string.Format(@"C:\{0}.txt", filename ?? "Untitled");
        }
  • Si le paramètre est marqué avec le mot-clé ref ou out, la valeur par défaut ne peut pas être définie.

Lors de l'appel d'une méthode avec des paramètres facultatifs ou nommés, faites attention aux règles et principes supplémentaires suivants :

  • Les paramètres réels peuvent être dans n'importe quelle commande est passée, mais les arguments nommés ne peuvent apparaître qu'à la fin de la liste des arguments .

  • Les paramètres sans valeurs par défaut peuvent être transmis par nom, mais tous les arguments requis doivent être transmis (soit par position, soit par nom).

  • C# ne permet pas d'omettre les paramètres réels entre virgules, tels que M(1,,DateTime.Now). Pour les paramètres avec des valeurs par défaut, si vous souhaitez omettre leurs paramètres réels, transmettez simplement les paramètres réels en passant le nom du paramètre.

  • Si le paramètre nécessite ref/out, afin de transmettre le paramètre réel en passant le nom du paramètre, veuillez utiliser la syntaxe suivante :

        //方法声明:
        private static void M(ref int x) { ...}
    
        //方法调用:
        int a = 5;
        M(x: ref a);
  • Lorsque C# appelle un composant COM, si les paramètres réels sont passés par référence, C# permet également d'omettre ref/out pour simplifier davantage le codage. Mais si l'appel n'est pas un composant COM, C# exige que le mot-clé ref/out soit appliqué aux paramètres réels.

9.1.2 DefaultParameterValueAttribute etOptionalAttribute

9.2 Variables locales implicitement typées

  • Impossible d'utiliser var pour déclarer le type des paramètres de méthode.

  • Vous ne pouvez pas utiliser var pour déclarer des champs dans un type.

  • Ne confondez pas dynamique avec var . Déclarer des variables locales avec var n'est qu'une syntaxe simplifiée qui oblige le compilateur à déduire le type de données spécifique en fonction de l'expression. Le mot-clé var ne peut déclarer que des variables locales à l'intérieur d'une méthode, tandis que le mot-clé dynamic s'applique aux variables locales, aux champs et aux paramètres. L'expression ne peut pas être convertie en var, mais elle peut être convertie en dynamique. Les variables déclarées avec var doivent être explicitement initialisées, mais les variables déclarées avec dynamic n'ont pas besoin d'être initialisées.

        private static void ImplicitlyTypedLocalVariables()
        {
            var name = "Jeff";
            ShowVariableType(name); //显示:System.String

            //var n=null;           //错误,不能将null赋给隐式类型的局部变量
            var x = (String)null;   //可以这样写,但意义不大
            ShowVariableType(x);    //显示:System.String

            var numbers = new int[] { 1, 2, 3, 4 };
            ShowVariableType(numbers);  //显示:System.Int32[]

            //复杂类型能少打一些字
            var collection = new Dictionary<String, Single>() { { "Grant", 4.0f } };

            //显示:System.Collections.Generic.Dictionary`2[System.String,System.Single]
            ShowVariableType(collection);

            foreach (var item in collection)
            {
                //显示:System.Collections.Generic.KeyValuePair`2[System.String,System.Single]
                ShowVariableType(item);
            }
        }

        private static void ShowVariableType<T>(T t)
        {
            Console.WriteLine(typeof(T));
        }

9.3 Passer les paramètres aux méthodes par référence

  • CLR utilise par défaut tous les paramètres de méthode passant par valeur.

  • CLR permet de transmettre les paramètres par référence plutôt que par valeur. C# prend en charge cette fonctionnalité en utilisant les mots-clés out ou ref.

  • CLR ne fait pas de distinction entre out et ref, et le même code IL sera généré quel que soit le mot-clé utilisé. De plus, les métadonnées sont presque exactement les mêmes, à l'exception d'un bit, qui est utilisé pour enregistrer si out ou ref a été spécifié lors de la déclaration de la méthode.

  • Le compilateur C# traite ces deux mots-clés différemment, et cette différence détermine quelle méthode est responsable de l'initialisation de l'objet référencé.

  • La méthode utilisant out pour marquer le paramètre ne peut pas lire la valeur du paramètre et doit écrire dans cette valeur avant de revenir. Au contraire, si une méthode est marquée par ref, la valeur du paramètre doit être initialisée avant d'appeler la méthode. La méthode appelée peut lire la valeur et/ou écrire dans la valeur

    <.>
  • est utilisé
  • out

        public static void Main()
        {
            int x;                  //x没有初始化
            GetVal(out x);          //x不必初始化
            Console.WriteLine(x);   //显示“10”
        }
    
        private static void GetVal(out int v)
        {
            v = 10; //该方法必须初始化v
        }
  • en utilisant
  • ref

        public static void Main()
        {
            int x = 5;              //x已经初始化
            GetVal(ref x);          //x必须初始化
            Console.WriteLine(x);   //显示“15”
        }
    
        private static void GetVal(ref int v)
        {
            v += 10; //该方法可使用v的已初始化的值
        }
  • ne peut pas être défini uniquement dans la référence Méthodes surchargées différentes de out.
  • La variable passée à la méthode par référence doit être du même type que le type déclaré dans la signature de la méthode.
  •     public static void Main()
        {
            string s1 = "Jeffrey";
            string s2 = "Richter";
    
            //错误!错误!错误!
            //Swap(ref s1, ref s2);   
    
            //以传引用的方式传递的变量,
            //必须和方法预期的匹配
            object o1 = s1, o2 = s2;
            Swap(ref o1,ref o2);
    
            //完事后再将object转型为string
            s1 = (string)o1;
            s2 = (string)o2;
    
            Console.WriteLine(s1);   //显示“Richter”
            Console.WriteLine(s2);   //显示“Jeffrey”
        }
    
        private static void Swap(ref object a, ref object b)
        {
            object t = b;
            b = a;
            a = t;
        }
  • Vous pouvez utiliser des génériques pour modifier la méthode ci-dessus
  •     public static void Main()
        {
            string s1 = "Jeffrey";
            string s2 = "Richter";
    
            Swap(ref s1, ref s2);
            Console.WriteLine(s1);   //显示“Richter”
            Console.WriteLine(s2);   //显示“Jeffrey”
        }
    
        private static void Swap<T>(ref T a, ref T b)
        {
            T t = b;
            b = a;
            a = t;
        }

9.4 向方法传递可变数量的参数

  • params 只能应用于方法签名中的最后一个参数。

  • 这个参数只能标识一维数组(任意类型)。

  • 可为这个参数传递 null 值,或传递对包含零个元素的一个数组的引用。

  • 调用参数数量可变的方法对性能有所影响(除非显式传递null)。要减少对性能的影响,可考虑定义几个没有使用 params 关键字的重载版本,如System.String类的Concat方法。

        public static void Main()
        {
            Console.WriteLine(Add(new int[] { 1, 2, 3, 4, 5 }));//显示“15”
            //或
            Console.WriteLine(Add(1, 2, 3, 4, 5));              //显示“15”

            //以下两行都显示“0”
            Console.WriteLine(Add());       //向Add传递 new int[0]
            Console.WriteLine(Add(null));   //向Add传递 null :更高效(因为不会分配数组)
        }

        private static int Add(params int[] values)
        {
            // 注意:如果愿意,可将values数组传给其他方法

            int sum = 0;
            if (values != null)
            {
                for (int x = 0; x < values.Length; x++)
                    sum += values[x];
            }
            return sum;
        }

9.5 参数和返回类型的设计规范

  • 声明方法的参数类型时,应尽量指定最弱的类型,宁愿要接口也不要基类。例如,如果要写方法来处理一组数据项,最好是用接口(比如 IEnumerable8742468051c85b06f0a0af9e3e506b5c)声明参数,而不要用强数据类型(比如List8742468051c85b06f0a0af9e3e506b5c)或者更强的接口类型(比如ICollection8742468051c85b06f0a0af9e3e506b5cIList8742468051c85b06f0a0af9e3e506b5c):

        //好:方法使用弱参数类型
        public void ManipulateItems<T>(IEnumerable<T> collection){}
    
        //不好:方法使用强参数类型
        public void ManipulateItems<T>(List<T> collection) { }
  • 相反,一般最好是将方法的返回类型声明为最强的类型(防止受限于特定类型)。例如,方法最好返回FileStream而不是Stream对象:

        //好:方法使用强返回类
        public FileStream OpenFile() { }
    
        //不好:方法使用弱返回类
        public Stream OpenFile() { }
  • 如果想保持一定的灵活性,在将来更改方法返回的东西,请选择一个较弱的返回类型。

        //灵活:方法使用较弱的返回类型
        public IList<string> GetStringCollection() { }
    
        //不灵活:方法使用较强的返回类型
        public List<string> GetStringCollection() { }

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn