1、類
定義類的語法:
[訪問修飾符] class類名
{
成員;字段、屬性、方法都可以叫做類的成員,他們都需要定義訪問的級別
}
最好一個類定義成一個cs文件並且類名和文件名起相同
類名一般使用pascal命名法
對象:
特徵:屬性:對象具有的各種屬性:屬性的值
行爲:方法:執行的操作
怎麼產生一個對象?
類是對象的類型
通過屬性和方法來描述一個對象
類的實例化:
通過類來產生一個對象的過程叫做類的實例化(對象名或者叫做實例名)
語法:
類名實例名=new類()//new一下別忘了括號
Person zsperson=new person()
Person zsperson;
zsperson=new person;
相當於先定義一個變量zsperson,然後通過new產生一個對象並把產生的對象賦給變量zsperson
類的成員的訪問:
實例名.屬性 實例名.方法名()
Person zsperson=new person()
zsperson.name=“張三”
zsperson.sayhello()
program p=new program();
p.aaa();
附:String name=null與string name=“”區別?
例子:
class person
{
public int age //建議加public,不加public則訪問不到了
public char sex
public string name
public void sayhello()在自己定義的類中,寫方法時先不加static!!
靜態方法只能訪問靜態的屬性,所以用非靜態的
{
Console.Writeline(“輸出“)
}
//Static void method()靜態方法:
//此處的method就可以不用實例化直接類名.方法名person.method就可以了因此
//這種情況可以單獨定義個類而不用和不加的混在一起導致混亂(個人理解)
{
}
static void main(string[] args)
{
Person zsperson=null;只聲明瞭變量沒有實例化這個屬性,
Person zsperson=new Person();
zsperson.name=“張三”;
zsperson.age=10;
zsperson.sex=’男’;
zsperson.sayhello();
string name= zsperson.name;
}
只要是沒有加static的方法和屬性,都必須先實例化()new,再通過實例名.方法名或者實例名.屬性來訪問
加static的方法或者屬性可以直接通過類名.方法名或類名.屬性名來訪問
Class program
{
int test;
void method()
static void main(string[] args)
{
test是訪問不到的,program.test也訪問不到
必須先實例化類Program p=new Program
p.test=””;
p.method();就可以訪問了
Class program
{
static int test;
static void method()在main方法同一個類內部定義的方法一般都加static
Static void main(string[] args)
{
//直接可以通過類名.方法,名類名.屬性名訪問
program.test;
Program.method();可以訪問到
如果是訪問本類(同在program一個類中)的屬性和方法還可以省略類名進行訪問test;method();這樣就和之前的感覺一樣了
Console.writeline爲什麼可以訪問到就是加了static
類中定義方法時前面不要加static,因爲在靜態訪問時只能訪問靜態的屬性不能訪問實例屬性,main方法是static靜態的
不需要new時加static 需要new後再調用則不加static
所以會出現在自己定義的類中定義方法時不加static
在main方法內部調用定義的方法時要加static
所以:在自己定義的類中,寫方法時先不加static!!!!!!!!!!!!!!!!!!
附:
不僅類能定義方法,結構也可以定義方法int.tryparse就是結構中定義的類
2、public訪問修飾符引申
訪問級別的用處在於控制成員在哪些地方可以被訪問,這樣達到面向對象中封裝的目的
四個訪問修飾符:
public private( internal protected)
Public可以在任何地方被訪問
Private只能在本類中被訪問
Internal只能在本項目中被訪問
Protected只能在本類中和子類中被訪問
如果一個類中定義變量或方法時,沒加public則默認爲private
在類的裏面方法的外面默認訪問修飾符爲private
在命名空間內,在類這個級別不寫訪問修飾符默認爲internal (如結構、枚舉)
多個項目之間的調用時才考慮到internal
講三層架構時:
層與層之間類的調用,自己手動加上public
3、字段和屬性
類中直接定義的變量其實應該叫做字段,不能叫做屬性。
方法中定義的變量沒有訪問修飾符這一說,不允許加訪問修飾符
定義的變量稱爲局部變量,只在方法內有效
屬性:
定義一個public變量,變量中含有get和set兩個方法,我們就叫做屬性(跟定義字段時差不多)
屬性是爲了保護與之相對應的字段的,保證對字段的讀取和賦值符合要求
凡是允許外部訪問的變量一定要聲明爲屬性,通過屬性保護起來才能保證賦值的合法性
先進行判斷先set判斷然後通過get返回
這樣age的值就能很好的保護起來,我們只要引用Age就行了
實例:
classPerson
{
publicchar sex;
publicstring name;
privateint age; //先改爲私有的
publicint Age //通過一個公共屬性(變量)保護一個私有變量
{ //我們只看到Age而沒有看到age,從而通過訪問屬性來保護字段的過程就是封裝的概念
get
{
return age;//返回小寫的age
}
set
{
if (value >= 0)//這裏有個關鍵字,value中存儲着用戶賦的那個值
{
age =value;
}
else
{
age = 0;
}
}
}
}
classProgram
{
staticvoid Main(string[] args)
{
Person zsperson =new Person();
zsperson.sex ='男';
zsperson.name ="張三";
zsperson.Age = 15;
int aaa = zsperson.Age;
Console.WriteLine("我是{0},性別{1},年齡{2}", zsperson.sex,zsperson.name, zsperson.Age);
}
}
微軟自動生成get set屬性的過程:
{
privateint age; //先private保護起來不讓用戶訪問到
//int age; //在類中不寫修飾符默認爲private
publicint Age //公有的用大寫開頭pascal 私有的用小寫開頭camel
{
get
{
return age;
} //取值
set
{
age =value;
} //賦值(檢測)value就是存儲用戶賦的那個值
}
privatechar sex;//在這一行右鍵重構,點封裝,確定就變成了 或者使用快捷鍵Ctrl R+E
publicchar Sex
{
get {return sex; }
set { sex =value; }
}
//不管前面是private還是public封裝之後就都是private了
}
讀寫屬性:
只讀只寫讀寫區別就是get/set的擁有個數、
只讀;有get沒set
只寫;沒get有set
讀寫;get set兩個方法都有
4、構造方法
當我們實例化一個類的時候,系統會自動對這個類的屬性進行初始化。
然後我們賦值,所以對象中必須對屬性賦值
爲什麼會出現構造方法:
1、有隻讀屬性的時候在什麼地方賦值
2、一旦只讀則在實例化時也將不能賦值了
3、不能在類定義中直接賦值,因爲以後調用時實例化的其他對象將會一樣
使用構造方法的好處:
1、對多個屬性進行賦值時,不需要重複的寫實例名
2、可以保證用戶在new一個對象的時候必須對某一個屬性進行賦值
3、在創建對象時,對只讀屬性可以進行初始化
怎麼創建構造方法:如何定義構造方法:
當我們定義好一個類之後,如果我們沒有寫構造方法,那麼系統就會自動給我們加上一個默認的沒有參數的構造方法,在這個構造方法中什麼也不做,我們也看不到
這就是即使沒有寫構造方法格式也得這樣寫的原因。
Student zsstudent=new Student();創建對象時,有這個括號其實就是在調用構造方法
構造方法特點:構造方法是一個特殊的方法,他的名字和類的名字相同,並且沒有返回值,連void都可以省了不寫,我們一旦手寫一個構造方法後,系統原先默認給我們添加的那個無參的構造方法就不會再爲我們添加了
構造方法:方法的名稱和類的名稱一樣,並且沒有返回值
什麼時候調用構造方法? 在初始化類的成員時
要實例化一個類必須調用它的構造方法
構造方法傳參來對變量進行初始化
構造方法可以有多個參數,將參數賦給相應的字段,也可以賦給屬性。
例子:
namespace構造方法練習
{
///<summary>
///類中設置構造方法
///</summary>
classStudent
{
//***怎麼確定是構造方法?方法的名稱與類名相同並且沒有返回值!!!!!!!!***
public Student() //如果定義了有參構造方法的時候,就把默認的屏蔽掉了
//要想調用無參數的構造方法則必須重新定義
//根據重載可以自己再寫一個無參的構造方法,本身就構成了重載
{
}
public Student(stringname,intage) //定義構造方法,不加public是訪問不到的
{
//字段this.name=參數name; //this.name指示代詞當前類中的字段
//字段顏色一樣的是指向一個字段this.name=參數name;
this.name=name;
this.age =age;
}
public Student(string name,int age, char sex,int chinese,int math,int english)
//構造方法的重載
{
this.name = name;
this.age = age;
this.sex = sex;
this.chinese = chinese;
this.math = math;
this.english = english;
}
//一般使用構造方法都是用於對類的成員進行初始化
//定義構造方法時內部的參數必須在下面有相對應
string name;
publicstring Name
{
get {return name; }
}
//set{ } 只有get沒有set變成只讀的!!
int age;
publicint Age
{
get {return age; }
set { age =value; }
}
char sex;
publicchar Sex
{
get {return sex; }
set { sex =value; }
}
int math;
publicint Math
{
get {return math; }
set { math =value; }
}
int chinese;
publicint Chinese
{
get {return chinese; }
set { chinese =value; }
}
int english;
publicint English
{
get {return english; }
set { english =value; }
}
publicvoid SayHello()
{
Console.WriteLine("我是{0},我的性別是{1},年齡是{2}", name, sex, age);
}
publicvoid ShowScore()
{
Console.WriteLine("數學成績{0},語文成績{1},英語成績{2}", math, chinese, english);
}
}
}
namespace構造方法練習
{
classProgram
{
staticvoid Main(string[] args)
{
//要實例化一個類必須調用它的構造方法
Student aa =newStudent();//自己定義的一個無參數的構造方法,默認自動賦初值
Student zsStudent =new Student("張三", 18);
//再zsstudent.name=“張四”;是錯誤的
只讀屬性只能在構造方法實例化的時候賦值
//zsStudent.Name="張三";
//zsStudent.Age=18;
zsStudent.Sex ='男';//等其他一樣
zsStudent.Math = 87;
zsStudent.Chinese = 98;
zsStudent.English = 86;
Student xlStudent =new Student("小蘭", 16,'女', 85, 68, 96);//要實例化一個類必須調用它的構造方法,只能調用有參數的構造方法,並且參數個數對應相同
//zsStudent.Name="小路";
//zsStudent.Age=16;
//zsStudent.Sex='女';
//zsStudent.Math=85;
//zsStudent.Chinese=68;
//zsStudent.English=96;
Console.WriteLine("下面輸出的是默認情況:");
aa.SayHello();
aa.ShowScore();
Console.WriteLine("下面輸出的是張三學生的學習成績:");
zsStudent.SayHello();
zsStudent.ShowScore();
Console.WriteLine("下面輸出的是小蘭學生的學習成績:");
xlStudent.SayHello();
xlStudent.ShowScore();
Console.ReadKey();
}
}
}
5、構造方法的重載
構造方法的重載和一般方法是一樣的
要實例化一個類必須調用它的構造方法
初始化類的成員時常用到構造方法
對屬性方法進行賦值
當對類的成員賦值時,如果一個全部賦值一個只想賦三個怎麼辦?
通過構造方法的重載來解決
方法的重載:
用到在同一個類中,方法的名稱相同,參數個數不同對應位置類型不同
方法是可以重載的,構造方法同樣可以重載
6、、認識類圖
拿到類:
首先看有什麼構造方法及其參數,才能實例化的時候確定調用那些構造方法和傳那些參數
****實例化之後需要關心那些屬性和方法可以讓我們來調用***
其實我們只關心類中的方法就行了,方法的功能方法的使用就行了。具體內部怎麼實現的不關心
當代碼複雜的時候查找是比較麻煩的,所以引出類圖
矩形通用類圖
1層 類名student
2層 字段和屬性
-age:int
-name:string
+Name:string
-表示私有private +表示公有public
3層 方法 +Sayhi():void
C#專用類圖:
右鍵:“查看類關係圖”
7、可變參數params
int sum=Sum(1,2,3,4,5);
Console.Writeline(sum);
static int Sum(paramsint[] arr)//怎麼回事一下子能傳好幾個?上面int的是sum不
是數組?????自動變成了一個數組?!
{
}
static int Sum(paramsint[] arr,int age)正確
static int Sum(int age,paramsint[] arr) 錯誤
可變參數必須作爲最後一個參數
8、命名空間:
命名空間是解決類重名問題,可以看做類的文件夾
相同名字的類產生衝突,最好將類放到命名空間裏面
命名空間中放類:
一個命名空間肯定是在一個文件中?不一定可能很多類放到相同命名空間下
訪問位置和要訪問的類在同一個命名空間namespace下能直接訪問到類名,
則不需要using
如果不在同一個命名空間下則不能直接訪問
在不同的命名空間下的類在調用有兩種方法:
a、寫全稱命名空間.類名 System.Threading.Thread 調用線程這個類
b、先 using 引用命名空間再調用(即導入命名空間)
(自動引用(ctrl+.)在保證把類名寫準了)
所有的命名空間都在system命名空間中
常用命名空間
threading
text
data
collection
命名空間下可以包含命名空間
項目?
不是在一個文件下嵌套幾層,而是再建一個文件,在定義時指定爲上級命名空間下的命名空間
.net的命名空間表示的是邏輯上的劃分
真實文件下的命名空間表示的是物理上的
9、字符串操作處理
類與結構的關係:
string類
string可以看做char的只讀數組
string =”abcdefg”;
for(int i;i<s.Length;i++)
{
console.write(s[i]);
}
C#中string的特性:字符串一旦聲明賦值就不能改變,是隻讀的
只能通過索引來讀取指定位置的char,不能對指定位置的char進行修改
如果要改變某一元素的值
char[] chars=to.chararray();通過to.chararray得到字符數組
方法s.tochararray的返回值是char數組
chars[2]=’i’ ;修改字符數組的值,char數組的修改不會造成字符串的改變
s=new string(chars);通過調用字符串構造方法new string(char[]),創建chars數組的新字符串
console.write(s);
聚焦:像person類也可以不new可是卻不能將對象賦值給他
而string類可以直接用“ ”括起來就是字符串直接賦值
例:
大小寫識別: C#與c#
判斷全轉大寫或轉小寫之後比較
string scoreA=”C#”;
string scoreA=”c#”;
if(scoreA==scoreB)
{
console.writeline(“選擇相同課程”)
}
else
{ console.writeline(“選擇相同課程”)
}
10、引申:
msdn自學
string類常用方法
查看類msdn靜態非靜態才知道怎麼調用這個類
字符串是不可改變的所以這些函數都不會直接改變字符串的內容,而是把修改後的字符串的值通過函數返回值的形式返回
[訪問修飾符] abstract class 類名
Tostring方法
.length屬性
ToLower(); 取得字符串的小寫形式
ToUpper(); 取得字符串的大寫形式
Trim(); 去掉字符串兩端的空白
s1.Equals(s2,StringComparison.OrdinallgnoreCase)
兩個字符串進行比較不區分大小寫返回bool類型
string.Equals()方法
scoreA.Tolower();
string str= scoreB.Tolower();//字符串本身沒有改變必須用一個字符串來接收
scoreA = scoreA.Tolower();//可以賦值回去
scoreB = scoreB.Tolower();
console.writeline();
if(scoreA== scoreB) //區分大小寫
if(scoreA.Equals(scoreB))//區分大小寫
if(scoreA.Equals(scoreB,StringComparison.OrdinallgnoreCase)//忽略大小寫
{console.writeline(“選的課相同”);
}
else
{ console.writeline(“選的課不同”);
}
string[] Split(params char[] separator );
string str=” How are you?Fine,thank you!”;
string [] words=str.Split(‘ ’,’?’,’!’,’,’);//char數組
不能一個一個字符放進去,params
char [] removeChar={‘ ’,’?’,’!’,’,’}
string [] words=str.Split(removeChar ,StringSplitOptions. (枚舉)RemoveEmptyEntries);
console.writeline(“這句話有{0}個單詞。”,words.Length)
console.writeline(“這幾個單詞分別是:”)
for(i=0;i<words.length;i++)
{
console.writeline(words[i]);
}
console.readline();
console.writeline(“{0}{1}{2}”,words) 傳數組
console.writeline(“{0}{1}{2}”,words[1],words[],words[]) 傳元素
練習:分析字符串2008-08-08輸出2008年08月08日 string.split(‘-’)
分析字符串2008/08/08輸出2008年08月08日string.split(‘-’,’/’)
string [] sp=data.Split(new char[] {‘-’,’/’} ,StringSplitOptions.
RemoveEmptyEntries);
console.writeline(“{0}年{1}月{2}日”,sp)
字符串的不可改變性:
變量指向的字符串改變了
不是該字符串的內容改變了
該字符串就一直在那
只不過是變量名字指向了新的字符串
string str=“hello word!”;
str=“abc”;
str=str.replace(“b”,“d”);
s1=“hello word!!”
string s10=s1;
s1=“abcdefg”;
此時s10仍然指向“hello word!!”這個字符串
詳情請查看: