在声明时不带修饰符的形参就是值参数
一个值参数对应一个局部变量,它的初始值来自该方法调用所提供的相应实参。值参数是实参的副本,对值参数的操作不会影响变量的值
internal class Program
{
static void Main(string[] args)
{
Tool tool = new Tool();
int x = 20;
int y = 40;
tool.Add(x, y);
Console.WriteLine(x);
//打印60和20
}
}
class Tool
{
public void Add(int x, int y)
{
x = x + y;
Console.WriteLine(x);
}
}
internal class Program
{
static void Main(string[] args)
{
User user = new User() { ID = "111" };
Method(user);
Console.WriteLine(user.ID);
//打印123和111
}
static void Method(User user)
{
user = new User() { ID = "123" };
Console.WriteLine(user.ID);
}
}
class User
{
public string ID { get; set; }
}
internal class Program
{
static void Main(string[] args)
{
User user = new User() { ID = "111" };
Method(user);
Console.WriteLine("HashCode = {0}, ID = {1}", user.GetHashCode(), user.ID);
//此时Hash码和ID都相同
}
static void Method(User user)
{
user.ID = "123";//没有创建新对象
//此为方法的副作用(side-effect),在实际使用中应该避免方法的这些副作用
Console.WriteLine("HashCode = {0}, ID = {1}",user.GetHashCode(),user.ID);
}
}
class User
{
public string ID { get; set; }
}
在声明时使用了 ref 修饰符声明的形参,不会创建副本,引用参数所表示的存储位置是在方法调用中作为实参给出的那个变量所表示的存储位置
变量在作为引用参数传递前,必须先明确赋值
static void Main(string[] args)
{
int x = 10;
Method(ref x);
Console.WriteLine(x);//打印20
}
static void Method(ref int x)
{
x += 10;
}
internal class Program
{
static void Main(string[] args)
{
User user = new User() { ID = "111" };
Console.WriteLine("HashCode = {0}, ID = {1}", user.GetHashCode(), user.ID);
Method(ref user);
Console.WriteLine("HashCode = {0}, ID = {1}", user.GetHashCode(), user.ID);
//打印三行
//第一次打印与后面不同
//方法调用后的两次的Hash码和ID都相同
}
static void Method(ref User user)
{ //Hash码变化后是因为方法体中new了一个新值
user = new User() { ID = "123" };
Console.WriteLine("HashCode = {0}, ID = {1}", user.GetHashCode(), user.ID);
}
}
class User
{
public string ID { get; set; }
}
internal class Program
{
static void Main(string[] args)
{
User user = new User() { ID = "111" };
Console.WriteLine("HashCode = {0}, ID = {1}", user.GetHashCode(), user.ID);
Method(ref user);
Console.WriteLine("HashCode = {0}, ID = {1}", user.GetHashCode(), user.ID);
//三次打印出来后Hash码都相同
//方法调用后,对象(ID)值改变
}
static void Method(ref User user)
{
user.ID = "123";
Console.WriteLine("HashCode = {0}, ID = {1}", user.GetHashCode(), user.ID);
}
}
class User
{
public string ID { get; set; }
}
用 out 修饰符声明的参数,输出参数不创建新的存储位置
变量在作为输出参数传递前,不需要赋值
在方法返回时,该方法的每一个输出参数都必须明确赋值
传值参数:利用副作用修改值
输出参数:利用副作用向外输出
Console.WriteLine("Input Num1:>");
string arg1 = Console.ReadLine();
double x = 0;
bool b1 = double.TryParse(arg1, out x);
//TryParse方法返回一个bool类型的值
//将string类型的值转换为double类型的值并输出
if(b1 == false)
{
Console.WriteLine("Input error");
return;
}
Console.WriteLine("Input Num2:>");
string arg2 = Console.ReadLine();
double y = 0;
bool b2 = double.TryParse(arg2, out y);
if (b2 == false)
{
Console.WriteLine("Input error");
return;
}
Console.WriteLine("{0} + {1} = {2}", x, y, x + y);
internal class Program
{
static void Main(string[] args)
{
User user = null;
bool b = UserFactory.Create("JACK", 1233431, out user);
if(b==true)
{
Console.WriteLine("User:> {0}\nCode:> {1}", user.ID, user.Code);
}
}
}
class User
{
public string ID { get; set; }
public int Code { get; set; }
}
class UserFactory//创建User
{
public static bool Create(string userID, int userCode, out User result)
{
result = null;
if (string.IsNullOrEmpty(userID))
{
return false;
}
result = new User() { ID = userID, Code = userCode };
return true;
}
}
声明时由params修饰
未使用数组参数:
static void Main(string[] args)
{
int[] intArray = { 1, 2, 3 };
int result = CalculateSum(intArray);
Console.WriteLine(result);
}
static int CalculateSum(int[] nums)
{
int sum = 0;
foreach (var i in nums)
{
sum += i;
}
return sum;
}
使用数组参数:
static void Main(string[] args)
{
int result = CalculateSum(1, 2, 3);//无须声明一个数组
Console.WriteLine(result);
}
static int CalculateSum(params int[] nums)
{ //数组参数
int sum = 0;
foreach (var i in nums)
{
sum += i;
}
return sum;
}
数组参数一些例子:
int x = 100;
int y = 200;
int z = x + y;
Console.WriteLine("{0} + {1} = {2}", x, y, z);
string str = " USSR; MOS, RS";
string[] result = str.Split(';', ',');//Split可以分割字符串
foreach (string area in result)
{
Console.WriteLine(area);
}
注意:在一个方法的参数列表中,只能有一个参数由params修饰,且此参数为参数列表中最后一个参数
调用方法时,传入的参数带有名字
不具名调用:
static void Main(string[] args)
{
Print("Jack", 18);
}
static void Print(string name, int age)
{
Console.WriteLine("{0} is {1} years ago", name, age);
}
具名调用:
static void Main(string[] args)
{
Print(name: "Jack", age: 18);
}
static void Print(string name, int age)
{
Console.WriteLine("{0} is {1} years ago", name, age);
}
优点:
在调用某个方法时,此参数可传入也可以不传入
当不写时,此参数默认获得声明时的值
static void Main(string[] args)
{
Print(name: "John");
}
static void Print(string name = "Jack", int age = 18)
{
Console.WriteLine("{0} is {1} years ago", name, age);
}
double pi = 3.1415926;
double a = Math.Round(pi, 2);
//Round方法第一个值是对谁四舍五入
//第二个值是精确到第几位
Console.WriteLine(a);
double类型没有Round方法,只能依靠Math
而扩展方法可以使用double类型调用Round方法
internal class Program
{
static void Main(string[] args)
{
double pi = 3.1415926;
double a = pi.Round(2);//.前面的pi就是第一个参数,只输入第二个参数
Console.WriteLine(a);
}
}
static class DoubleExtension
{
public static double Round(this double input, int digits)
{
double result = Math.Round(input, digits);
return result;
}
}
注意:
写一个能接收集合类型的参数的方法,判断集合中的值是否都大于10
未使用LINQ方法:
static void Main(string[] args)
{
List<int> myList = new List<int>() { 10, 20, 30 };
bool b = ItemBiggerTen(myList);
Console.WriteLine(b);
}
//上为方法调用,下为方法
static bool ItemBiggerTen(List<int> intList)
{
foreach (int i in intList)
{
if (i <= 10)
{
return false;
}
}
return true;
}
使用LINQ方法:
static void Main(string[] args)
{
List<int> myList = new List<int>() { 10, 20, 30 };
bool b = myList.All(i => i > 10);//查看所有元素是否都大于10
//All方法可以接收委托类型的参数
Console.WriteLine(b);
}
上段代码中的 All() 方法就是扩展方法,不属于List类,而属于Enumerable这个静态类