声明时不带修饰符的形参是值形参。一个值形参对应于一个局部变量,只是它的初始值来自该方法调用所提供的相应实参。
注意:(1)值参数创建变量的副本(2)对值参数的操作永远不影响变量的值
```c#
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Student stu = new Student();
int y = 100;
stu.AddOne(y);
Console.WriteLine(y);
}
}
class Student
{
public void AddOne(int x)
{
x += 1;
Console.WriteLine(x);
}
}
}
### (2)引用类型
- 新创建对象

```c#
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Student stu = new Student() { Name = "Tim" };
SomeMethod(stu);
Console.WriteLine("{0},{1}",stu.GetHashCode(),stu.Name);
}
static void SomeMethod(Student stu)
{
stu = new Student() { Name = "Tom" };
Console.WriteLine("{0},{1}", stu.GetHashCode(),stu.Name);
}
}
class Student
{
public string Name { get; set; }
}
}
只操作对象,不创建新对象
注意:对象还是那个对象,但对象里的值(字段/属性)已经改变
```c#
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Student stu = new Student() { Name = "Tim" };
UpdateObiect(stu);
Console.WriteLine("HashCode={0},Name={1}", stu.GetHashCode(),stu.Name);
}
static void UpdateObiect(Student stu)
{
stu.Name="Tom";
Console.WriteLine("HashCode={0},Name={1}", stu.GetHashCode(),stu.Name);
}
}
class Student
{
public string Name { get; set; }
}
}
## 2、引用参数
引用形参是用ref修饰符声明的形参。与值形参不同,引用形参并不创建新的存储位置。相反,引用形参表示的存储位置恰是在方法调用中作为实参给出的那个变量所表示的存储位置。变量在可以作为引用形参传递之前,必须先明确赋值。
### (1)值类型

>注意:(1)引用参数并不创建变量的副本
(2)使用ref修饰符显式指出——此方法的副作用是改变实际参数的值
```c#
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
int y = 1;
IWantSideEffect(ref y);
Console.WriteLine(y);
}
static void IWantSideEffect(ref int x)
{
x+=1;
}
}
创建新变量
```c#
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Student outterStu = new Student() { Name = "Tim" };
Console.WriteLine("HashCode={0},Name={1}", outterStu.GetHashCode(), outterStu.Name);
Console.WriteLine("---------------------------");
IWantSideEffect(ref outterStu);
Console.WriteLine("HashCode={0},Name={1}", outterStu.GetHashCode(), outterStu.Name);
}
static void IWantSideEffect(ref Student stu)
{
stu = new Student() { Name = "Tom" };
Console.WriteLine("HashCode={0},Name={1}",stu.GetHashCode(),stu.Name);
}
}
class Student
{
public string Name { get; set; }
}
}
- 不创建新对象,只改变对象值

>注意:此时与传值参数在效果上并无不同,但机理不一样,有些面试题会考到
```c#
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Student outterStu = new Student() { Name = "Tim" };
Console.WriteLine(" Hashcod={0},Name={1}", outterStu.GetHashCode(), outterStu.Name);
Console.WriteLine("--------------------------------");
SomeSideEffect(ref outterStu);
Console.WriteLine(" Hashcod={0},Name={1}", outterStu.GetHashCode(), outterStu.Name);
}
static void SomeSideEffect(ref Student stu)
{
stu.Name = "Tom";
Console.WriteLine(" Hashcod={0},Name={1}", stu.GetHashCode(), stu.Name);
}
}
class Student
{
public string Name { get; set; }
}
}
用out修饰符声明的形参是输出形参。类似于引用形参,输出形参不创建新的存储位置。相反,输出形参表示的存储位置恰是在该方法调用中作为实参给出的那个变量所表示的存储位置。变量在可以作为输出形参传递之前不一定需要明确赋值。在方法返回之前,该方法的每个输出形参都必须明确赋值。
(1) 输出参数并不创建变量的副本
(2) 方法体内必需要有对输出变量的赋值的操作
(3) 使用out修饰符显式指出-------此方法的副作用是通过参数向外输出值
(4) 从语义上来讲----------ref是为了“改变" , out是为了"输出”
```c#
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Please input first number:");
string arg1 = Console.ReadLine();
double x = 0;
bool b1 = double.TryParse(arg1, out x);
if (b1==false)
{
Console.WriteLine("input error!");
return;
}
Console.WriteLine("Please input second number:");
string arg2 = Console.ReadLine();
double y = 0;
bool b2 = double.TryParse(arg2, out y);
if (b2 == false)
{
Console.WriteLine("input error!");
return;
}
double z = x + y;
Console.WriteLine("{0}+{1}={2}",x,y,z);
}
其中TryParse方法
```c#
class DoubleParser
{
public static bool TryParse(string input,out double result)
{
try
{
result = double.Parse(input);
return true;
}
catch
{
result = 0;
return false;
}
}
}
}
引用类型
```c#
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Student stu = null;
bool b = StudentFactory.Create("Tim", 34, out stu);
if (b==true)
{
Console.WriteLine("Student {0},age is {1}.",stu.Name,stu.Age);
}
}
}
class Student
{
public int Age { get; set; }
public string Name{ get; set; }
}
class StudentFactory
{
public static bool Create(string stuName,int stuAge,out Student result)
{
result = null;
if (string.IsNullOrEmpty(stuName))
{
return false;
}
if (stuAge<20||stuAge>80)
{
return false;
}
result = new Student() { Name = stuName, Age = stuAge };
return true;
}
}
}
## 4、数组参数
- 必需是形参列表中的最后一个,由params修饰
- 举例: String.Format方法和String.Split方法。
```c#
class Program
{
static void Main(string[] args)//无需声明一个数组
{
int result = CalculateSum(1,2,3);
Console.WriteLine(result);
}
static int CalculateSum(params int[] intArray)
{
int sum = 0;
foreach (var item in intArray)
{
sum += item;
}
return sum;
}
}
```c#
static void Main(string[] args)
{
string str = "Tim;Tom,Amy.Lisa";
string[] result = str.Split(‘;‘, ‘,‘, ‘.‘);
foreach (var name in result)
{
Console.WriteLine(name);
}
}

## 5、具名参数
- 参数的位置不要再受约束
```c#
class Program
{
static void Main(string[] args)
{
PrintInfo(name: "Tim", age: 34);
}
static void PrintInfo(string name,int age)
{
Console.WriteLine("Hello {0},You are {1}",name,age);
}
}
```c#
class Program
{
static void Main(string[] args)
{
List<int> myList = new List<int>() { 11, 12, 13, 14, 15 };
bool result = myList.All(i=>i>10);
Console.WriteLine(result);
}
}
C#语言入门(10)传值/输出/引用/数组/具名/可选参数,扩展方法
原文:https://blog.51cto.com/u_15296868/3245905