C#基础-第9章:参数

说明:第2部分:第9章:参数P(185)
  8.1 本章内容:
  1. 可选参数和命名参数
  2. 隐式类型的局部变量
  3. 以传引用的方式向方法传递参数,out,ref
  4. 向方法传递可变数据量的参数:params
  5. 参数和返回类型的设计规范:传入弱类型,返回强类型。
  6. 常量性
#define V1
//#define V2
//#define V3

using System;
using System.Collections.Generic;

public static class Parameters
{
    public static void Main()
    {
        OptionalAndNamedParameters.Go();
        MethodsThatTakeVariableArguments.Go();

        OutAndRefParameters.SomeMethod();
    }
}

internal static class OptionalAndNamedParameters
{
    private static Int32 s_n = 0;

    public static void Go()
    {
        ImplicitlyTypedLocalVariables();//P(185)

        //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()); 
        //PS:s_n 先传值,再++
        M(s_n++, s_n++.ToString());

        // 5. 等同于: String t1 = "2"; Int32 t2 = 3; 
        //             M(t2, t1, default(DateTime), new Guid());
        M(s: (s_n++).ToString(), x: s_n++);
    }

    private static void M(Int32 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);
    }

    private static void ImplicitlyTypedLocalVariables()//P(188)
    {
        /***************** 隐形类型的局部变量 **********************/
        var name = "Jeff";
        ShowVariableType(name);    // 显示: System.String

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

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

        // 复杂类型能少打些字
        var collection = new Dictionary<String, Single>() { { ".NET", 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));
    }
}

/// <summary>
/// out ,ref参数的区别
/// </summary>
internal static class OutAndRefParameters
{
#if V1
    public static void Go() //P(190)
    {

        Int32 x;               // x 没有初始化
        SetVal(out x);         // x 不必初始化,
                               //out 在调前不需要初始化,而ref不需要,其实CLR是不区分out ref的。 
        Console.WriteLine(x);  // 显示 "10"
    }

    private static void SetVal(out Int32 v)
    {
        v = 10;  //该方法必须初始化
    }
#endif
#if V2
        public static void Main()  //P(191) {
            Int32 x = 5;         // x 已经初始化
            AddVal(ref x);        // X 必须初始化
            Console.WriteLine(x); // 显示 "15"
        }

        private static void AddVal(ref Int32 v) {
            v += 10;  // 该方法可以使用v的已初始化的值
        }
#endif
#if V3
        public static void Main() {
            Int32 x;              // x没有有初始化

            // 下一行代码无法通过编译,编译器将报告:
            // error CS0165: 使用了未赋值的局部变量 'x'.
            AddVal(ref x);

            Console.WriteLine(x);
        }

        private static void AddVal(ref Int32 v) {
            v += 10;  // 该方法可以使用v的已初始化的值
        }
#endif
    //下面演示了如何用ref关键字实现一个用于交换两个引用类型的方法:
    
    public static void Swap(ref Object a, ref Object b)
    {
        Object t = b;
        b = a;
        a = t;
    }
    public static void Swap<T>(ref T a, ref T b) 
    {
        T t = b;
        b = a;
        a = t;
    }
#if true
    public static void SomeMethod()//P(193)
    {
        String s1 = "Jeffrey";
        String s2 = "Richter";
        Swap(ref s1, ref s2);    // 这里调用不是上面的 Swap(object,object) 而是 Swap<T>,因为编译不通过,
                                 // PS: ref ,out 的参数类型必须和方法保持一致。SomeMethod2 才是正确的表达。
        Console.WriteLine(s1);  // 显示 "Richter"
        Console.WriteLine(s2);  // 显示 "Jeffrey"

    }

#endif

    public static void SomeMethod2()//P(194)
    {
        String s1 = "Jeffrey";
        String s2 = "Richter";

        // 以传引用的方式传递的变量,
        // 必须和方法预期的匹配
        Object o1 = s1, o2 = s2;
        Swap(ref o1, ref o2);  //这里调用才是 Swap(object,object)

        // 完事后再将object转型为String
        s1 = (String)o1;
        s2 = (String)o2;

        Console.WriteLine(s1);  // 显示 "Richter"
        Console.WriteLine(s2);  // 显示 "Jeffrey"
    }


}

internal static class MethodsThatTakeVariableArguments
{
    public static void Go()
    {
        // 显示 "15"
        Console.WriteLine(Add(new Int32[] { 1, 2, 3, 4, 5 }));

        // 显示 "15"
        Console.WriteLine(Add(1, 2, 3, 4, 5));

        // 显示 "0"
        Console.WriteLine(Add());

        DisplayTypes(new Object(), new Random(), "Jeff", 5);
    }
    // params 参数为可以变数量参数的关键字
    private static Int32 Add(params Int32[] values)//P(195)
    {
        // 注意:如果愿意,可以将values数组传给其它方法
        Int32 sum = 0;
        for (Int32 x = 0; x < values.Length; x++)
            sum += values[x];
        return sum;
    }


    private static void DisplayTypes(params Object[] objects)
    {
        foreach (Object o in objects)
            Console.WriteLine(o.GetType());
    }
}

///////////////////////////////////////////////////////////////////////////////

public sealed class Point
{
    static void Add(Point p) { /* ... */ }
    static void Add(ref Point p) { /* ... */ }

    //Add 不能定义仅在ref和out是有差别的重载的方法。
    //下面这样不可以,不能这样重载.
    // static void Add(out Point p) { /* ... */ }
}

////////////////////////////// End of File ////////////////////////////////////

 

posted @ 2019-01-14 10:07  eric.yuan  阅读(125)  评论(0编辑  收藏  举报