class PhoneClass
{
public const string DayOfSendingBill = "Monday";
public int CustomerID;
public string FirstName;
public string LastName;
}
结构
struct PhoneStruct
{
public const string DayOfSendingBill = "Monday";
public int CustomerID;
public string FirstName;
public string LastName;
}
类是存储在堆(heap)上的引用类型,而结构是存储在栈(stack)上的值。较小的数据类型是使用结构,可提供性能。
类和结构,都需要使用 new 来声明实例。
PhoneClass phone = new PhoneClass()
PhoneStruct phone = new PhoneStruct()
对于复杂的数据类型,按引用传递效率更高,因为按值传递时,必须复制大量数据。
迫使值参数通过引用传送给方法,方法对变量所做的改变,都会影响原始对象值。
static void Main(string[] args)
{
int i = ;
Console.WriteLine("{0}",i);
Modify(ref i);
Console.WriteLine("{0}", i);
Console.ReadLine();
}
static void Modify(ref int i)
{
i = ;
}
C# 要求传递方法的参数必须进行初始化。
out关键字初始化,传递给该方法的变量可以不初始化,方法返回时,方法内对变量所做的改变,都会保留下来。
static void Main(string[] args)
{
int i;
Modify(out i);
Console.WriteLine("{0}", i);
Console.ReadLine();
}
static void Modify(out int i)
{
i = ;
}
允许是通过参数名,按任意顺序传递。
static void Main(string[] args)
{
Console.WriteLine("{0}", FullName("John", "Doe"));
Console.WriteLine("{0}", FullName(lastName: "Doe", firstName: "John"));
Console.ReadLine();
}
static string FullName(string firstName, string lastName)
{
return firstName + " " + lastName;
}
可选参数必须提供默认值,且必须是在定义在方法的最后的参数。
static void Main(string[] args)
{
Console.WriteLine("{0}", FullName(firstName: "John"));
Console.ReadLine();
}
static string FullName(string firstName, string lastName="Default")
{
return firstName + " " + lastName;
}
方法名相同,参数的个数 或 类型不同。
class TestFun
{
void DoFun(string result)
{
}
void DoFun(int result)
{
}
}
方法重载不能使用可选参数,可通过函数重载来实现此目的。
public void DoFun(string result)
{
this.DoFun(result, );
}
public void DoFun(string result,int index)
{
Console.WriteLine("DoFun2");
}
private string _someProperty;
public string SomeProperty
{
get { return _someProperty; }
set { _someProperty = value; }
}
自动实现属性
public string SomeProperty { get; set; }
属性访问修饰符
C#允许给属性的 get 和 set 访问器设置不同的访问修饰符。在 get 和 set 访问器中,必须有一个具备属性的访问级别。
public string SomeProperty { get; private set; }
通过属性访问字段,需要担心带来性能损失。C#代码会编译为IL,然后在运行时JIT编译为本地可执行代码。JIT编译器可以生成高度优化的代码,并在适当的时候随意地内联代码。任何内联代码完全有ClR决定,不能像C++中像 inline 这样关键字控制方法是否内联。
构造函数声明一个与类同名的方法,且没有返回类型。
class TestFun
{
private int _number;
public TestFun(int number)
{
this._number = number;
}
}
TestFun testFun = new TestFun();
class TestFun
{
private int _number;
private TestFun(int number)
{
this._number = number;
}
}
static TestFun()
{
}
静态构造函数,是在加载类时,有 .net 运行库调用它,静态构造函数不能带参数,一个类也只能有一个静态构造函数。静态构造函数只能访问静态成员,不能访问类的实例成员。
无参数的实例构造参数与静态构造参数可以同一类中同时定义。
class TestFun
{
public static readonly string BackColor;
static TestFun()
{
DateTime now = DateTime.Now;
switch (now.DayOfWeek)
{
case DayOfWeek.Monday:
BackColor = "Green";
break;
default:
BackColor = "Red";
break;
}
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("{0}",TestFun.BackColor);
Console.ReadLine();
}
}
class Car
{
public string description;
public uint numWheels;
public Car(string description, uint numWheels)
{
this.description = description;
this.numWheels = numWheels;
}
public Car(string description): this(description, )
{
}
//public Car(string description)
//{
// this.description = description;
// this.numWheels = 4;
//}
}
class Program
{
static void Main(string[] args)
{
Car car = new Car("Audio");
Console.WriteLine("{0} {1}",car.description,car.numWheels);
Console.ReadLine();
}
}
这是C# 特殊语法,称为构造函数初始化器。注意 初始化器不能有多个调用。
public Car(string description): this(description, )
只读字段只能在构造函数中给只读字段赋值,只读字段可以是一个实例字段。如果要把只读字段设置为静态,必须显示声明它。
public static readonly uint StaticCars;
static Car()
{
StaticCars = ;
}
public readonly uint SampleCars;
public Car()
{
SampleCars = ;
}
静态只读,只能在静态构造函数赋值。实例只读,在实例构造函数赋值。当然也可以在声明时赋值。
var 和 new 一起使用创建匿名类型。
var caption = new {FirstName = "James", LastName = "Leonard"};
结构是值类型,定义结构和类完全相同。
struct Car
{
public int nWheel;
public string description;
public Car(string description,int nWheel)
{
this.description = description;
this.nWheel = nWheel;
}
}
Car car = new Car("Audio",);
Console.WriteLine("{0} {1}",car.description,car.numWheels);
Car car2 = new Car();
car2.description = "BMW";
car2.numWheels = ;
Console.WriteLine("{0} {1}", car2.description, car2.numWheels);
结构分配内存时,速度非常快,因为它们将内联或者保存在栈中。在结构超出了作用作用域,删除也是很快。负面影响,当把结构作为参数传递时,结构的所有内容就被复制,对于类就不会。应使用 ref 参数传递,以避免性能损失。
构造函数的方式与类定义构造函数方式相同,但不允许定义无参数的构造函数。
结构不能在绕过构造函数进行赋值,否则会出现编译错误。
也可以像类一样 提供 Close 或 Dispose 方法。
只要有代码引用它,就会形成强引用。弱引用创建和使用对象,它在垃圾回收器回收时,就会回收对象并释放内存。
弱引用由 WeakReference 创建
MathTest math = new MathTest();
WeakReference mathReference = new WeakReference(math);
if (mathReference.IsAlive)
{
math = mathReference.Target as MathTest;
math.x = ;
math.y = ;
Console.WriteLine("{0}", math.Value);
}
partial 关键字允许把类、结构、方法或接口放在多个文件中。
用法放在 class、struct、interface前面。
// MathTest1.cs
partial class MathTest1
{
public void MethodOne()
{
}
}
// MathTest2.cs
partial class MathTest1
{
public void MethodTwo()
{
}
}
这样这个类 MathTest1 就拥有了 两个方法。
在 class 前面加上 static,就声明了静态类。静态类里不能拥有实例成员和函数。
static class Math
{
public static int Add(int x, int y)
{
return x + y;
}
}
class Program
{
static void Main(string[] args)
{
Math.Add(, );
Console.ReadLine();
}
}
如果定义类时没有指定基类,编译器就会自动假定这个类派生自 Object。
结构总是派生自 System.ValueType。 System.ValueType 又派生自 System.Object
class Money
{
public decimal amount;
public override string ToString()
{
return "$" + amount.ToString();
}
}
class Program
{
static void Main(string[] args)
{
Money money = new Money();
money.amount = ;
Console.WriteLine("{0}",money);
decimal amount = ;
Console.WriteLine("{0}", amount);
Console.ReadLine();
}
}
假设想在Money中添加一个方法 AddToAmount。但是由于某种原因不能在源文件中修改。此时可以扩展方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplicationCShape
{
public class Money
{
public decimal amount;
public override string ToString()
{
return "$" + amount.ToString();
}
}
class Program
{
static void Main(string\[\] args)
{
Money money = new Money();
money.amount = ;
money.AddToAmount();
Console.WriteLine("{0}",money);
Console.ReadLine();
}
}
}
namespace ConsoleApplicationCShape
{
public static class MoneyExtension
{
public static void AddToAmount(this Money money, decimal amountToAdd)
{
money.amount += amountToAdd;
}
}
}
如果扩展方法与类方法同名,就不会调用扩展方法。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章