把C#部分的知识点记录下来,以供日后复习。 菜鸟教程
- 前言
- 可空类型
- 继承
- 多态
- 运算符重载
- 接口(Interface)
- 预处理指令
- C# 特性(Attribute)
- C# 索引器(Indexer)
- C# 委托(Delegate)
- C# 事件(Event)
- C# 泛型(Generic)
- C# 匿名方法
- C# Lambda表达式
总结: 声明类型后面加?可以让不能为空的值为空。 ??和?.使用方法看代码示例。 可空类型
示例代码:
int? a;
a = null;
b = a??1;//如果a为空则返回1
//如果testClass为空则不会调用DoSomething方法
//省掉了判断testClass是否为空的步骤
testClass?.DoSomething();
继承
总结: C#不支持多重继承,但是可以继承多个接口。 实例只能向上兼容(子实父)。 派生类必须继承父类的构造函数,默认继承的无参构造函数。派生类继承构造函数时需要传入父类构造函数所需的参数,具体看代码示例。 继承
示例代码:
class Father
{
public Father(int a)
{
Console.WriteLine("Father:{0}",a);
}
public virtual void DoFather()
{
Console.WriteLine("Father");
}
}
class Son:Father
{
public Son(int a) : base(a) // a都是这里的int a
{
Console.WriteLine("Son:{0}", a);
}
public override void DoFather()
{
Console.WriteLine("Son");
}
}
class Program
{
static void Main(string[] args)
{
Father father = new Father(1);
father.DoFather(); //输出 Father:1 Father
Son son = new Son(1);
son.DoFather(); //输出 Father:1 Son1 Son
//Error 子类无法用父类实例
//Son sf = new Father() as Son;
//sf.DoFather();
Father fs = new Son(1);
fs.DoFather(); //输出 Father1 Son1 Son 和上一个相同
}
}
多态
总结: 1.多态是同一个行为具有多个不同表现形式或形态的能力。实现多态的手段:抽象类、虚方法、接口。 2.abstract类中可以包含抽象字段,抽象方法。也可以包含实现了的方法和字段(非abstract)。 3.abstract和virtual的区别:abstract是抽象,只需要声明不需要实现部分,它必须被覆写。virtual是虚方法。必须有实现部分(即使是空的大括号),可以不被覆写。 4.new和override的区别:new是隐藏方法,根据声明的class调用方法,如果声明是父类,即使是用子类实例的,也调用的父类。override是重写方法,看用的哪个类实例调用哪个类。 5.方法重载(overload)有三个条件,方法名必须相同,参数列表必须不相同,返回值类型可以不相同。(二必须一可以) 多态
运算符重载总结: 1.是静态方法,是重载不是覆写。 2.注意需要的参数和返回值。 3.使用operator关键字,后面跟上要重载的操作符。 4.不是所有操作符都可以重载,详细内容看教程。 运算符重载
示例代码:
public class Program
{
static void Main(string[] args)
{
OperatorTest a = new OperatorTest();
a.num = 5;
OperatorTest b = new OperatorTest();
b.num = 6;
OperatorTest c = a + b;
Console.WriteLine(c.num);
Console.ReadKey();
}
}
public class OperatorTest
{
public int num;
//运算符重载
public static OperatorTest operator +(OperatorTest a, OperatorTest b)
{
OperatorTest test = new OperatorTest();
test.num = a.num + b.num;
return test;
}
}
接口(Interface)
总结: 1.接口只是声明,不能有实现部分。继承类负责实现。 2.接口中可以定义事件,索引器,属性,方法。 3.默认访问权限为public。 4.接口之间可以继承。 4.通常接口命名以“I”开头。 5.is用于判断是否能转换,如if(a is b);as用于转换,不会报错,如果转换不了会返回null,如P p = a as P; 接口(Interface)
示例代码:
//简单使用
class Program
{
static void Main(string[] args)
{
IWorker james1 = new James1();
IWorker james2 = new James2();
james1.work("设计");
james2.work("编程");
//从这个例子我体会到了有接口的好处,可以想象如果又来了新的员工。
//如果不采用接口,而是每个员工都有一个单独的类,这样就会容易出错。
//如果有接口这种协议约束的话,那么只要实现了接口就肯定有接口里声明的方法,我们只需拿来调用。
}
}
public interface IWorker{ void work(string s); }
class James1 : IWorker
{
public void work(string s)
{
Console.WriteLine("我的名字是James1,我的工作是" +s);
}
}
class James2 : IWorker
{
public void work(string s)
{
Console.WriteLine("我的名字是James2,我的工作是"+s);
}
}
//接口继承
interface IParentInterface
{
void ParentInterfaceMethod();
}
interface IMyInterface : IParentInterface
{
void MethodToImplement();
}
class InterfaceImplementer : IMyInterface
{
static void Main()
{
InterfaceImplementer iImp = new InterfaceImplementer();
iImp.MethodToImplement();
iImp.ParentInterfaceMethod();
}
public void MethodToImplement()
{
Console.WriteLine("MethodToImplement() called.");
}
public void ParentInterfaceMethod()
{
Console.WriteLine("ParentInterfaceMethod() called.");
}
//接口中定义事件,索引器,属性,方法;
delegate void Delegate();
interface I
{
event Delegate DE;
T this[int i]
{
get;
set;
}
List age
{
get;
set;
}
void Say();
}
class c : I
{
public event Delegate DE;
public c this[int i]
{
get { return age[i]; }
set { DE(); Say(); age[i] = value; }
}
public List age
{
get;
set;
}
public void Say()
{
Console.WriteLine("123");
}
}
class b : I
{
public event Delegate DE;
public c this[int i]
{
get { return age[i]; }
set { DE();Say(); age[i] = value; }
}
public List age
{
get;
set;
}
public void Say()
{
Console.WriteLine("456");
}
}
class Program
{
static void Main(string[] args)
{
I Ic = new c();
I lb = new b();
Ic.DE += deC;
lb.DE += deB;
lb = Ic;
lb.age = new List();
lb.age.Add(new c());
lb[0] = new c();
Console.WriteLine("S");
Console.ReadKey();
}
static void deC()
{
Console.WriteLine("c");
}
static void deB()
{
Console.WriteLine("B");
}
}
预处理指令
总结: 1.一行只能有一个预处理器指令。 2.#define只在当前声明类生效。 3.预处理指令一般用于程序的调试和运行。 4.Unity可以使用#if UNITY_EDITOR等判断运行环境来确定是否执行后续代码。 预处理指令
示例代码:
#define test
using System;
namespace 预处理指令
{
class Program
{
static void Main(string[] args)
{
#if (test)
Console.WriteLine("test is define");
#else
Console.WriteLine("test is not define");
#endif
//#region可以折叠代码
#region 折叠
Console.ReadKey();
#endregion
}
}
}
C# 特性(Attribute)
总结: 1.特性分为两种,预定义特性和自定义特性。 2.预定义特性有AttributeUsage、Conditional、Obsolete、DllImport(用来标记非.NET的函数,表明该方法在一个外部的DLL中定义)。 3.每个特性至少有一个构造函数。 4.具体使用看下面代码,详细讲解看菜鸟教程。 C# 特性(Attribute)
示例代码:
// 描述如何使用一个自定义特性 SomethingAttribute
//参数1:支持在什么类型上加的特性;参数2:是否允许重复加该特性;参数3:是否支持特性继承;
[AttributeUsage(AttributeTargets.All , AllowMultiple = true , Inherited = true )]
//********自定义特性SomethingAttribute**************//
public class SomethingAttribute : Attribute
{
private string name; // 名字
private string data; // 日期
public string Name
{
get { return name; }
set { name = value; }
}
public string Data
{
get { return data; }
set { data = value; }
}
public SomethingAttribute(string name)
{
this.name = name;
}
}
//实例化自定义
//自动忽略名字中的Attribute部分,但是当作类使用的时候需要全名
[Something("Amy", Data = "2018-06-18")]
[Something("Jack", Data = "2018-06-18")]
class Test { }
class Program
{
static void Main(string[] args)
{
//获取自定义特性的中的变量
Type t = typeof(Test);
//这里是全名
var something = t.GetCustomAttributes(typeof(SomethingAttribute), true);
foreach (SomethingAttribute each in something)
{
Console.WriteLine("Name:{0}", each.Name);
Console.WriteLine("Data:{0}", each.Data);
Program p = new Program();
p.TestConditional();
p.OldMethod();
}
//如果存在此预定义符号(#define TEST),则执行此方法,没有则不执行,有点类似#if
//只能用于方法或特性类
[Conditional("TEST")]
public void TestConditional()
{
Console.WriteLine("Conditional test");
}
//true直接报错 false只是提醒,默认为false
[Obsolete("这个方法过时了!",false)]
public void OldMethod()
{
Console.WriteLine("Old");
}
}
//引用第三方类库 比如unity接入IOS就有用到
[DllImport("User32.dll")]
public static extern int MessageBox(int hParent, string Message, string Caption, int Type);
}
C# 索引器(Indexer)
总结: 1.索引器的用法类似属性。 2.索引器可以带有多个参数,并且支持多种类型。 3.作用相当于根据类的索引取对应的值。 C# 索引器(Indexer)
示例代码:
class IndexedNames
{
private string[] namelist = new string[size];
static public int size = 10;
public IndexedNames()
{
for (int i = 0; i = 0 && index = 0 && index
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?