1.方法的重载--【编译时的多态】
讲到方法的重载,概念性的东西,请看MSDN,我们还是看下例子吧:
示例一:
1.新建一个控制台程序:添加一个类【Overload】:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OOP1
{
/// <summary>
/// 编译时的多态:方法的重载
/// </summary>
public class Overload
{
/// <summary>
/// 方法的签名:包含方法的名字和参数(参数的数量和个数)
/// </summary>
/// <param name="a"></param>
public void DisplayOverload(int a)
{
Console.WriteLine("DisplayOverload: "+a);
}
/// <summary>
/// 方法的签名:包含方法的名字和参数(参数的数量和个数)
/// </summary>
/// <param name="a"></param>
public void DisplayOverload(string a)
{
Console.WriteLine("DisplayOverload: "+a);
}
/// <summary>
/// 方法的签名:包含方法的名字和参数(参数的数量和个数)
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
public void DisplayOverload(string a, int b)
{
Console.WriteLine("DisplayOverload: "+a +b);
}
}
}
主函数中:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OOP1
{
class Program
{
static void Main(string[] args)
{
Overload overload = new Overload();
overload.DisplayOverload(1000);
overload.DisplayOverload("Hello C# Method Overload");
overload.DisplayOverload("方法的重载", 2000);
Console.ReadKey();
}
}
}
运行程序:
阶段性总结:
1.方法重载,C#是根据传递过去的参数,来识别该调用哪个重载方法的,而不是方法名字!
2.方法的签名:由方法的名字和方法的参数和方法的数据类型组成!
示例二:
#region 错误1 :已定义了一个名为“DisplayOverload”的具有相同参数类型的成员
/// <summary>
/// 方法的返回值类型不是方法签名的一部分,所以,这两个方法不是方法重载,
/// </summary>
//public void DisplayOverload()
//{
// Console.WriteLine("Hello");
//}
/// <summary>
/// 方法的返回值类型不是方法签名的一部分,所以,这两个方法不是方法重载,
/// </summary>
//public int DisplayOverload()
//{
// return 1;
//}
#endregion
编译不通过,总结:方法的返回值类型,不是方法重载的一部分。
示例三:
#region 错误2:已定义了一个名为“DisplayOverload”的具有相同参数类型的成员
/// <summary>
/// 访问修饰符(例如:static),不是方法签名的一部分。
/// </summary>
/// <param name="a"></param>
//static void DisplayOverload(int a)
//{
//}
/// <summary>
/// 访问修饰符(例如:static),不是方法签名的一部分。
/// </summary>
/// <param name="a"></param>
//public void DisplayOverload(int a)
//{
//}
/// <summary>
/// 访问修饰符(例如:static),不是方法签名的一部分。
/// </summary>
/// <param name="a"></param>
//public void DisplayOverload(string a)
//{
//}
#endregion
编译不通过,总结:方法的访问修饰符,例如(static等),不是方法签名的一部分。
示例四:
上面的图中,有三个方法,编译的时候,两个错误,这里有点奇怪的是,我分别注释掉,第二个方法,和第三个方法,编译之后:都只剩下一个错误了。
总结:方法的签名不仅仅包含参数的数据类型,同样也包含参数的种类,例如ref 和out等。
所以进一步总结:方法的签名,不仅仅由方法的名称,参数的数量,参数的类型,还包括参数的形式组成。方法的返回值不是方法签名的一部分。两个方法不能有相同的签名,并且成员之间,不能有相同的名字。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
接着,讲一下,编译时的多态【方法重载】中的Params参数
一个方法,能够被下面四种类型的参数调用:
- 值类型的参数【By Value】
- 引用类型的参数【By reference】
- 输出参数【output参数】
- 参数数组【parameter arrays】
前面说到了,方法的访问修饰符,不是方法签名的一部分,现在我们来聚焦讨论参数数组。
方法的声明,会在内存中,创造一个独立的内存空间,所以:
这图中的第一个方法,参数名重复了,第二个方法,因为方法参数中已经声明过了。现在又在方法内声明一个名字一样的局部变量,也是不对的。
总结一下:参数的名字,必须是唯一的,并且在方法中,我们不能在已经有了一个参数名字,而在方法中在声明一个相同名称的局部变量!!!
示例五:
/// <summary>
/// 定义一个私有字段
/// </summary>
private string name = "daniel";
public void Display()
{
Dispaly2(ref name, ref name);
Console.WriteLine(name);
}
private void Dispaly2(ref string x, ref string y)
{
Console.WriteLine(name);
x = "Mike 1";
Console.WriteLine(name);
y = "Mike 2";
Console.WriteLine(name);
name = "Mike 3";
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OOP1
{
class Program
{
static void Main(string[] args)
{
Overload overload = new Overload();
overload.Display();
Console.ReadKey();
}
}
}
因为是引用传递,所以在方法内改变字段的值,原来的name字段值也改变了,(指针指向的地址是一样的。)
示例六:
public void Display()
{
DisplayOverload(300);
DisplayOverload(400, "Daniel", "深圳宝安");
DisplayOverload(800, "哇哈哈");
}
public void DisplayOverload(int a, params string[] parameterArray)
{
foreach (var item in parameterArray)
{
Console.WriteLine(item+" "+a);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OOP1
{
class Program
{
static void Main(string[] args)
{
Overload overload = new Overload();
overload.Display();
Console.ReadKey();
}
}
}
总结:使用参数数组,可以想传递多少个参数就传递多少个。参数数组必须是参数列表的最后一个,例如:
示例七:
public void Display()
{
DisplayOverload(100, 200, 300);
DisplayOverload(200, 100);
DisplayOverload(200);
}
private void DisplayOverload(int a, params int[] parameterArray)
{
foreach (var i in parameterArray)
Console.WriteLine(i + " " + a);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OOP1
{
class Program
{
static void Main(string[] args)
{
Overload overload = new Overload();
overload.Display();
Console.ReadKey();
}
}
}
总结:C#是非常智能的,可以识别出,第二个参数是否是相同的类型(和第一个参数类型int对比)
示例八;
总结:参数数组必须是一维数组。
示例九:
public void Display()
{
string[] names = { "Akhil", "Ekta", "Arsh" };
DisplayOverload(3, names);
}
private void DisplayOverload(int a, params string[] parameterArray)
{
foreach (var s in parameterArray)
Console.WriteLine(s + " " + a);
}
总结:我们允许,传递数组到参数数组中,而不是单个的string字符串。
示例十:
总结,第三个参数,是多余的。
示例十一:
public void Display()
{
int[] numbers = { 10, 20, 30 };
DisplayOverload(40, numbers);
Console.WriteLine(numbers[1]);
}
private void DisplayOverload(int a, params int[] parameterArray)
{
parameterArray[1] = 1000;
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OOP1
{
class Program
{
static void Main(string[] args)
{
//Overload overload = new Overload();
//overload.DisplayOverload(1000);
//overload.DisplayOverload("Hello C# Method Overload");
//overload.DisplayOverload("方法的重载", 2000);
//Console.ReadKey();
Overload overload = new Overload();
overload.Display();
Console.ReadKey();
}
}
}
总结:因为数组是引用类型,不管是什么类型的数组,所以numbers[1]变成了1000.
示例十二:
public void Display()
{
int number = 102;
DisplayOverload(200, 1000, number, 200);
Console.WriteLine(number);
}
private void DisplayOverload(int a, params int[] parameterArray)
{
parameterArray[1] = 3000;
}
因为number是值类型,在方法调用前后,值还是不变。
示例十四:
public void Display()
{
DisplayOverload(200);
DisplayOverload(200, 300);
DisplayOverload(200, 300, 500, 600);
}
private void DisplayOverload(int x, int y)
{
Console.WriteLine("The two integers " + x + " " + y);
}
private void DisplayOverload(params int[] parameterArray)
{
Console.WriteLine("parameterArray");
}
总结:方法的调用,是根据参数来的。
所以我们最后总结一下:
- C# recognizes the method by its parameters and not only by its name.【方法重载的时候,C#辨识方法是通过参数,不是方法名】
- The return value/parameter type of a method is never the part of method signature if the names of the methods are the same. So this is not polymorphism.【如果方法名称一样的话,方法的返回值类型,或者方法参数的类型从来都不是方法签名的一部分】
- Modifiers such as static are not considered as part of the method signature.【访问修饰符例如static不是方法签名的一部分】
- The signature of a method consists of its name, number and types of its formal parameters. The return type of a function is not part of the signature. Two methods cannot have the same signature and also non-members cannot have the same name as members.【方法的签名,是由方法的名称,参数的个数和参数的形式决定的,方法的返回值不是方法签名的一部分,两个方法不能有相同的签名,非成员之间也不能有相同的名称。】
- Parameter names should be unique. And also we cannot have a parameter name and a declared variable name in the same function.【参数的名字必须是唯一的,方法中已经有了一个参数,就不能在方法内在声明相同的名称的局部变量】
- In case of by value, the value of the variable is ed and in the case of ref and out, the address of the reference is ed.
- This params keyword can only be applied to the last argument of the method. So the n number of parameters can only be at the end.【parmas参数必须是方法参数列表的最后一个】
- C# is very smart to recognize if the penultimate argument and the params have the same data type.【C#可以自动判断参数列表中的数据类型】
- A Parameter Array must be a single dimensional array.【参数数组必须是一维数组】