一、方法及其调用
1、方法介绍:
1)功能:用来复用代码。当我们在一个程序中反复地写同样的代码,一般情况下,我们可以把需要重复写的代码定义在一个方法中,用的时候只需要调用就行了。
格式:[访问修饰符][static]返回值类型 方法名([参数])
{
方法体;
}
注意:a、一般情况下,方法一般要定义在类中;b、如果方法没返回值,则返回值类型写void;c、若一个方法一旦有参数,那么调用都就必须传参数,并且传参数的个数与对应位置上的类型必须一致。d、一个变量一旦定义在方法外,类的里面。这就叫做类的字段。如:static int a=10; static const double PI=3.14;这样的变量就可以被本类的所有方法所访问,但是要注意,静态方法只能访问静态字段。
2)命名规则:方法名开头大写,参数名开头小写,参数名、变量名要有意义。方法的调用,对于静态方法,如果在同一个类中,直接写名字调用就行了!
3)方法也称函数,函数就是将一堆代码进行重用的一种机制。函数就是一段代码,这段代码可能有输入的值(参数),可能会返回值。一个函数就像一个专门做某件事的人,我们调用它来做一些事情,它可能需要我们提供一些数据给它,它执行完成后可能会有一些执行结果给我们。要求的数据就叫参数,返回的执行结果就是返回值。
4)string s=Console.ReadLine()就是一个有返回结果的函数;Console.WriteLine("hello")就是一个有执行参数的函数,只有告诉WriteLine被打印的数据它才知道如何打印:int i=Convert.ToInt32("58");(只要方法中有返回值,就可以用一个变量来接收)则是一个既有参数又有返回值的函数。
5)有了函数写代码就像拼积木,C#中的各种各样的技术其实就是通过for、if等这些基础的语法将不同的函数按照一定的逻辑组织起来。当调用者想访问我们方法中的变量时,可以通过返回值返回。例如:
string s=Console.ReadLine()
int i=Convert.ToInt32
因在方法中使用了返回值,所以在方法前面能够定义一个变量收到方法的值。只要在方法中返回了值,那么在调用方法中,前面就应该用一个变量来接收方法的返回值。
2、方法的作用域:
1)在方法中定义的变量称为局部变量,其作用域从定义开始,到其所在的大括号结束为止。一个方法可以有多个返回值,要返回多个值可以用数组返回,但数组的所有元素的类 型必须相同。
2)在一个方法中想要访问另一个方法 中的变量,怎么办
eg1:接收的变量的类型也必须与方法的返回值一致
- <span style="font-size: 16px;">using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace 方法及调用
- {
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("您确定要关机吗?(y/n)");
- string str = ReadAnswer();//接收的变量的类型也必须与方法的返回值一致
- //获取main方法中用语输入的是y还是n
- if (str == "y")
- {
- Console.WriteLine("正在在关机……");
- }
- else
- {
- Console.WriteLine("不关机");
- }
- Console.ReadKey();
- }
- public static string ReadAnswer()
- {
- string result="";
- do
- {
- result = Console.ReadLine();
- if (result != "y" && result != "n")
- {
- Console.WriteLine("您的输入有误,请重新输入!");
- }
- } while (result != "y" && result != "n");
- //当方法执行完后,result中存储的就是用户输入的y或n
- return result;//将result作为返回值返回,必须要与方法的返回值类型一致
- }
- }
- }</span>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 方法及调用
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("您确定要关机吗?(y/n)");
string str = ReadAnswer();//接收的变量的类型也必须与方法的返回值一致
//获取main方法中用语输入的是y还是n
if (str == "y")
{
Console.WriteLine("正在在关机……");
}
else
{
Console.WriteLine("不关机");
}
Console.ReadKey();
}
public static string ReadAnswer()
{
string result="";
do
{
result = Console.ReadLine();
if (result != "y" && result != "n")
{
Console.WriteLine("您的输入有误,请重新输入!");
}
} while (result != "y" && result != "n");
//当方法执行完后,result中存储的就是用户输入的y或n
return result;//将result作为返回值返回,必须要与方法的返回值类型一致
}
}
}
eg2:计算两个整数的平均值。(用简单的程序练习)
- <span style="font-size: 16px;">using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace 方法及调用
- {
- class Program
- {
- static void Main(string[] args)
- {
- //计算两个整数的平均值
- Console.WriteLine("请输入一个整数");
- int a = int.Parse(Console.ReadLine());
- Console.WriteLine("请再输入一个整数");
- int b = int.Parse(Console.ReadLine());
- int sum = Add(a, b);
- Console.WriteLine("输入的两个整数的平均值为:{0}", sum / 2);
- Console.ReadKey();
- }
- public static int Add(int a, int b)
- {
- return a + b;
- }
- }
- }</span>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 方法及调用
{
class Program
{
static void Main(string[] args)
{
//计算两个整数的平均值
Console.WriteLine("请输入一个整数");
int a = int.Parse(Console.ReadLine());
Console.WriteLine("请再输入一个整数");
int b = int.Parse(Console.ReadLine());
int sum = Add(a, b);
Console.WriteLine("输入的两个整数的平均值为:{0}", sum / 2);
Console.ReadKey();
}
public static int Add(int a, int b)
{
return a + b;
}
}
}
eg3: 让用户输入一个年份,判断是否为闰年。(方法及其调用练习)
- <span style="font-size: 16px;">using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace 方法及调用
- {
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("请输入一个年份,判断是否闰年");
- int year = Convert.ToInt32(Console.ReadLine());
- bool result = LeapYear(year);
- if (result)//不能用true或false代替
- {
- Console.WriteLine("此年份是闰年");
- }
- else
- {
- Console.WriteLine("不是闰年");
- }
- Console.ReadKey();
- }
- public static bool LeapYear(int year)
- {
- if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- }
- }</span>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 方法及调用
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("请输入一个年份,判断是否闰年");
int year = Convert.ToInt32(Console.ReadLine());
bool result = LeapYear(year);
if (result)//不能用true或false代替
{
Console.WriteLine("此年份是闰年");
}
else
{
Console.WriteLine("不是闰年");
}
Console.ReadKey();
}
public static bool LeapYear(int year)
{
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
return true;
}
else
{
return false;
}
}
}
}
二、什么是构造方法?
1)关于构造方法总结:
a、构造方法用来创建对象,并且可以在构造函数中对对象进行初始化,是最先调用的方法。
b、构造方法是用来创建对象的特殊方法,方法名和类名一样,没有返回值,也可以省略void不写。
c、构造函数可以有参数,new对象的时候传递函数参数即可。
d、如果不指定构造函数,则类有一个默认的无参构造函数;如果指定了构造函数,则不再有默认的无参构造函数,如果需要无参构造函数,则需要自己来写。
e、构造函数可以重载,也就是有多个参数不同的构造函数。
注:当我们定义好一个类之后,如果我们没有写构造方法,那么系统会自动给我们加上一个默认的没有参数的构造方法。在这个构造方法中什么也不做,我们也看不到。当我们自定义一个构造方法后,系统原先默认给我们添加的那个无参的构造方法就不会再为我们添加了。构造方法进行传,来对变量进行初始化。
2)使用构造方法的好处:
a、对多个属性进行赋值,不需要重复的写实例名;
b、可以保证用户在new一个对象的时候必须对某一个属性进行赋值
3) 调用构造方法的问题:
构造方法只能通过以下方式被调用:
a、当前类的其他构造方法通过this语句调用它。
b、当前类的子类的构造方法通过super语句调用它。
c、在程序中通过new语句调用它。
4)思考:方法如何定义及定义后如何调用?
public class A
{ public int GetInt()
{
} //在A类中定义个方法
}
public class B
{ A a =new A(); //实例化A的对象
a.GetInt(); //在B类中调用A类的方法
}
如果是静态的方法就不需要实例化 直接调用
public class A{ public static int GetInt(){} //在A类中定义个方法}
public class B{ A.GetInt(); //在B类中调用A类的方法}
三、方法中参数与返回值的三种情况:
a、没有参数没有返回值 b、有参数没有返回值 c、有参数有返回值
下面就这几种情况分别举例:
1、没有参数没有返回值 象这种情况最简单。
存储过程
use Northwind
create proc novalue noparameter as select* from products go
/// <summary>
/// c#代码 方法1
/// </summary>
SqlConnection conn = new SqlConnection();
conn.ConnectionString = strConn;
conn.Open();
SqlCommand comm = new SqlCommand("EXEC novaluenoparameter", conn);
comm.ExecuteNonQuery();
conn.Close();
情况2、有参数没有返回值
存储过程(带参数,没有返回值)
CREATE PROC novaluebeparameter
@i int ,
@productname varchar(20) AS SELECT TOP @i * FROM products where productname = @productname GO
/// <summary>
/// C#代码:调用带参数没有返回值的存储过程
/// </summary>
SqlConnection conn = new SqlConnection();
conn.ConnectionString = strConn;
conn.Open();
SqlCommand comm = new SqlCommand("novaluebeparameter", conn); //“novaluebeparameter”是存储过程名
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.Add(new SqlParameter("@i",SqlDbType.Int));
comm.Parameters.Add(new SqlParameter("@productname",SqlDbType.varchar,20));
comm.Parameters["@i"].Value=3;
comm.Parameters["@productname"].value = "Tofu"
comm.ExecuteNonQuery();
conn.Close();
3、带参数,有返回值(返回一个值,这里说下,有返回一个值的,有返回一个数据集的。)
四、利用参数返回值的练习:
1) 使用out实现通过参数传值:
out是内部为外部变量赋值,out一般用在函数需要有多个返回值的场所。
a、在方法的参数类型前加out,那么传参数的时候,也必须在number前加out表明这个参数不是参数传入的,而是用来传出值的。
b、如果参数是以out形式传入的,那么在传入之前可以不赋值。
c、在方法中对于由out修饰的参数,必须赋值,并且必须在使用前赋值。
2) out与ref的区别:out用于传出值,在方法中必须对out修饰的参数进行赋值;ref可以理解成是双向的,即可以传入,也可以传出。在传参的过程中,如果参数有out或ref修饰的话,那么改变方法中的参数变量的值,调用者方法量的值也会相应改变。
eg1:利用IntTryParse方法接收用语输入的字符串,并把它转换为int型,若转换成功则返回ture,若失败则返回false。
- <span style="font-size: 16px;">using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace 参数返回值练习
- {
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("请输入一个字符串(可以为纯数字):");
- string s = Console.ReadLine();
- int re;
- if (IntTryParse(s, out re))
- {
- Console.WriteLine("转换成功!" + re);
- }
- else
- {
- Console.WriteLine("转换失败!");
- }
- Console.ReadKey();
- }
- static bool IntTryParse(string s, out int result)
- {
- result = 0;
- try
- {
- result = Convert.ToInt32(s);
- return true;
- }
- catch
- {
- return false;
- }
- }
- }
- }</span>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 参数返回值练习
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("请输入一个字符串(可以为纯数字):");
string s = Console.ReadLine();
int re;
if (IntTryParse(s, out re))
{
Console.WriteLine("转换成功!" + re);
}
else
{
Console.WriteLine("转换失败!");
}
Console.ReadKey();
}
static bool IntTryParse(string s, out int result)
{
result = 0;
try
{
result = Convert.ToInt32(s);
return true;
}
catch
{
return false;
}
}
}
}
eg3:利用ref参数返回值,即可往里传值,以可往外传值
- <span style="font-size: 16px;">using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace 利用ref参数传值
- {
- //ref即可往里传值,以可往外传值
- class Program
- {
- static void Main(string[] args)
- {
- int number = 100;
- Test(ref number);
- Console.WriteLine(number);
- Console.ReadKey();
- }
- static void Test(ref int a)
- {
- int b = a;
- a = 500;
- }
- }
- }
- </span>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 利用ref参数传值
{
//ref即可往里传值,以可往外传值
class Program
{
static void Main(string[] args)
{
int number = 100;
Test(ref number);
Console.WriteLine(number);
Console.ReadKey();
}
static void Test(ref int a)
{
int b = a;
a = 500;
}
}
}
eg2:用多种方法实现:利用参数返回值(代码中加了"//"的是用不同方法实现,不是注释哦)
- <span style="font-size: 16px;">using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace 利用参数返回值
- {
- class Program
- {
- static void Main(string[] args)
- {
- //方法一:不用参数返回值
- //int number = 10;//可以在Test方法的参数前加out,不用赋值也能使用
- //int result = Test(number);
- //Console.WriteLine("number={0} result={1}", number, result);
- //Console.ReadKey();
- //方法二:利用参数返回值(形式一)
- //int number;//可以在Test方法的参数前加out,不用赋值也能使用
- //int result = Test(out number);//参数前也要加out,通过参数返值
- //Console.WriteLine("number={0} result={1}", number, result);
- //Console.ReadKey();
- //方法三:利用参数返回值(形式二)
- string str = "123abc";
- int turn;
- if (int.TryParse(str, out turn) == true)
- {
- Console.WriteLine("能转换成功,转换后的数为:{0}", turn);
- }
- else
- {
- Console.WriteLine("转换不成功");
- }
- Console.ReadKey();
- }
- //static int Test(int a)
- //{
- // a = 20;
- // return 20;
- //}
- static int Test(out int a)//out表对外传值
- {
- a = 10;//方法中对a赋值相当于对number赋值
- return 20;
- }
- }
- }</span>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 利用参数返回值
{
class Program
{
static void Main(string[] args)
{
//方法一:不用参数返回值
//int number = 10;//可以在Test方法的参数前加out,不用赋值也能使用
//int result = Test(number);
//Console.WriteLine("number={0} result={1}", number, result);
//Console.ReadKey();
//方法二:利用参数返回值(形式一)
//int number;//可以在Test方法的参数前加out,不用赋值也能使用
//int result = Test(out number);//参数前也要加out,通过参数返值
//Console.WriteLine("number={0} result={1}", number, result);
//Console.ReadKey();
//方法三:利用参数返回值(形式二)
string str = "123abc";
int turn;
if (int.TryParse(str, out turn) == true)
{
Console.WriteLine("能转换成功,转换后的数为:{0}", turn);
}
else
{
Console.WriteLine("转换不成功");
}
Console.ReadKey();
}
//static int Test(int a)
//{
// a = 20;
// return 20;
//}
static int Test(out int a)//out表对外传值
{
a = 10;//方法中对a赋值相当于对number赋值
return 20;
}
}
}
eg3:写一个方法,计算一个int类型数组中每个元素的总和和最大值、最小值?(一个方法返回多个值的情况)
- <span style="font-size: 18px;">using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace 一个方法返回多个值
- {
- class Program
- {
- static void Main(string[] args)
- {
- int[] nums = { 5, 16, 32, 45, 57, 68, 75, 85, 89, 91, 93 };
- int sum, min, max;
- sum = compute(nums, out max, out min);
- Console.WriteLine("数组的和为:{0} 最大值为:{1} 最小值为:{2}", sum,max,min);
- Console.ReadLine();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="numbers"></param>
- /// <param name="max">最大值</param>
- /// <param name="min">最小值</param>
- /// <returns>和</returns>
- static int compute(int[] numbers, out int max, out int min)
- {
- int sum = 0;
- max = numbers[0];
- min = numbers[0];
- for (int i = 0; i < numbers.Length; i++)
- {
- sum += numbers[i];
- if (numbers[i] > max)
- {
- max = numbers[i];
- }
- if (numbers[i] < min)
- {
- min = numbers[i];
- }
- }
- return sum;
- }
- }
- }</span>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 一个方法返回多个值
{
class Program
{
static void Main(string[] args)
{
int[] nums = { 5, 16, 32, 45, 57, 68, 75, 85, 89, 91, 93 };
int sum, min, max;
sum = compute(nums, out max, out min);
Console.WriteLine("数组的和为:{0} 最大值为:{1} 最小值为:{2}", sum,max,min);
Console.ReadLine();
}
/// <summary>
///
/// </summary>
/// <param name="numbers"></param>
/// <param name="max">最大值</param>
/// <param name="min">最小值</param>
/// <returns>和</returns>
static int compute(int[] numbers, out int max, out int min)
{
int sum = 0;
max = numbers[0];
min = numbers[0];
for (int i = 0; i < numbers.Length; i++)
{
sum += numbers[i];
if (numbers[i] > max)
{
max = numbers[i];
}
if (numbers[i] < min)
{
min = numbers[i];
}
}
return sum;
}
}
}
五、方法重载:一般在同一个类中,方法名相同,并且方法的参数个数不同或者对应位置上的类型不同(两个同名方法中参数的类型和个数相同时不能实现),才能构成方法的重载。
【构造方法的重载】问题
C#中构成函数重载有哪些条件和特征?
1.函数名;
2.函数返回值类型;
3.函数参数类型;
4.函数参数个数;
5.函数参数顺序;
以下是我个人总结的(仅供参考)
1、函数名必须相同方能构成函数重载;
2、函数返回值类型:可以相同,也可以不同(注意:函数的返回类型不足以区分两个重载函数);
3、函数参数类型:必须不同;
4、函数参数个数:可以相同,可以不同
5、函数参数顺序:可以相同,可以不同;
6、注意:参数表的比较过程与参数名无关.
注意:方法重载和返回值没有关系。如:
static void SayHello(string name)
{
Console.Writeline("我是{0}",name);
}
static int SayHello(string name)
{
return 10;
}分析:因这两个同名方法对应位置上的参数类型和个数都相同,所以不能构成重载。
在C#中,构造函数可以使用this关键字调用同一对象中的另一构造函数。和 base 一样,this 可带参数使用也可不带参数使用,构造函数中的任何参数都可用作 this 的参数,或者用作表达式的一部分。
- namespace 重载构造函数
- {
- class Program
- {
- static void Main(string[] args)
- {
- Employee emp1 = new Employee();
- Employee emp2 = new Employee("Tom");
- Employee emp3 = new Employee("Lee", 30);
- Console.WriteLine("使用默认构造方法:Name={0}, Age={1}", emp1.Name, emp1.Age);
- Console.WriteLine("使用带名字参数的构造方法:Name={0}, Age={1}", emp2.Name, emp2.Age);
- Console.WriteLine("使用带全参数的构造方法:Name={0}, Age={1}", emp3.Name, emp3.Age);
- Console.ReadLine();
- }
- }
- public class Employee {
- string name;
- int age;
- public int Age
- {
- get { return age; }
- set { age = value; }
- }
- public string Name
- {
- get { return name; }
- set { name = value; }
- }
- /// <summary>
- /// 默认构造方法
- /// </summary>
- public Employee()
- :this("NoName", 0)
- {
- //name = "NoName";
- }
- /// <summary>
- /// 带名字参数的构造方法
- /// </summary>
- /// <param name="name"></param>
- public Employee(string name)
- : this(name, 0)
- {
- //name = name;
- }
- /// <summary>
- /// 带全参数的构造方法
- /// </summary>
- /// <param name="name"></param>
- /// <param name="age"></param>
- public Employee(string name, int age) {
- name = name;
- age = age;
- }
- }
- }
namespace 重载构造函数
{
class Program
{
static void Main(string[] args)
{
Employee emp1 = new Employee();
Employee emp2 = new Employee("Tom");
Employee emp3 = new Employee("Lee", 30);
Console.WriteLine("使用默认构造方法:Name={0}, Age={1}", emp1.Name, emp1.Age);
Console.WriteLine("使用带名字参数的构造方法:Name={0}, Age={1}", emp2.Name, emp2.Age);
Console.WriteLine("使用带全参数的构造方法:Name={0}, Age={1}", emp3.Name, emp3.Age);
Console.ReadLine();
}
}
public class Employee {
string name;
int age;
public int Age
{
get { return age; }
set { age = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
/// <summary>
/// 默认构造方法
/// </summary>
public Employee()
:this("NoName", 0)
{
//name = "NoName";
}
/// <summary>
/// 带名字参数的构造方法
/// </summary>
/// <param name="name"></param>
public Employee(string name)
: this(name, 0)
{
//name = name;
}
/// <summary>
/// 带全参数的构造方法
/// </summary>
/// <param name="name"></param>
/// <param name="age"></param>
public Employee(string name, int age) {
name = name;
age = age;
}
}
}