(1)new List并不是null,可以正常的被遍历和AddRange

class Program
{
public static void Main()
{
//var t = new test();
//t.b = 100;
//Console.WriteLine($"{t.b}");
var a = new List<int> { 1, 2 };
var b = new List<int>();
a.AddRange(b);
foreach (var c in b)
{
Console.WriteLine($"{c}"); }
Console.WriteLine($"{b.Count}");
Console.WriteLine($"{b == null}"); }
}

(2)属性可以被private访问修饰符修饰,但这样就不能被实例从外部访问,一般是public或protected。

 class test
{
private int a { get; set; } public int b { get { return a; } set { a = 100; } }
}
class Program
{
public static void Main()
{ var t = new test();
Console.WriteLine($"{t.a}");
t.b = 100;
Console.WriteLine($"{t.b}"); }
}

(3)for 循环

int a = 1;
for (int i = 1; i < a; i++)
{
Console.WriteLine("h");
}

一次也没运行,for 循环的执行顺序是:

for (Initializer;TestExpr;IterationExpr)
Statement

在for 循环的开始,执行一次Initializer,然后对TestExpr求值,如果它返回true,执行Statement,接着是IterationExpr,然后控制回到循环的顶端,再次对TestExpr求值,依次进行,直到返回false,就继续执行Statement之后的语句。

(4) 虚方法与覆写方法,基类访问

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ConsoleApp1
{ class A
{
public virtual void Print()
{
Console.WriteLine("this is a");
}
}
class B:A
{
public override void Print()
{
Console.WriteLine("this is b");
}
}
class Program
{ public static void Main()
{ B b= new B();
A a = (A)b;
a.Print();
B c = (B)a;
c.Print(); } }
}

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ConsoleApp1
{ class A
{
public void Print()
{
Console.WriteLine("this is a");
}
}
class B:A
{
new public string Print()
{
Console.WriteLine("this is b");
return "yes";
}
}
class Program
{ public static void Main()
{ B b= new B();
A a = (A)b;
a.Print();
B c = (B)a;
c.Print(); } }
}

虚方法与覆写方法是成对存在的,并且要求函数除了签名一样,返回类型也一样,在派生类转为基类时,调用转化后的基类的虚方法,调用的是派生类的覆写方法。而使用new来屏蔽基类函数,则不要求返回类型一样,只要签名一样就可以了,并且派生类转为基类后,调用转化后的基类的“被屏蔽的方法”就是基类的“被屏蔽的方法”,而不再是派生类的方法。

(5)虚方法,抽象类,接口对实现多态的一点感想

多态就是:允许将子类类型的指针赋值给父类类型的指针。也就是同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。

  • a 首先,我们先来看下怎样用虚方法实现多态

    我们都知道,喜鹊(Magpie)、老鹰(Eagle)、企鹅(Penguin)都是属于鸟类,我们可以根据这三者的共有特性提取出鸟类(Bird)做为父类,喜鹊喜欢吃虫子,老鹰喜欢吃肉,企鹅喜欢吃鱼。创建基类Bird如下,添加一个虚方法Eat(),依次对Magpie,Eagle,Penguin添加重载方法。
    /// <summary>
/// 鸟类:父类
/// </summary>
public class Bird
{
/// <summary>
/// 吃:虚方法
/// </summary>
public virtual void Eat()
{
Console.WriteLine("我是一只小小鸟,我喜欢吃虫子~");
}
}

最后

    static void Main(string[] args)
{
//创建一个Bird基类数组,添加基类Bird对象,Magpie对象,Eagle对象,Penguin对象
Bird[] birds = {
new Bird(),
new Magpie(),
new Eagle(),
new Penguin()
};
//遍历一下birds数组
foreach (Bird bird in birds)
{
bird.Eat();
}
Console.ReadKey();
}

以上程序也体现了开放封闭原则,如果后面的同事需要扩展我这个程序,还想再添加一个猫头鹰(Owl),很容易,只需要添加一个Owl类文件,继承Bird,重写Eat()方法,添加给父类对象就可以了。至此,该程序的扩展性得到了提升,而又不需要查看源代码是如何实现的就可以扩展新功能。这就是多态带来的好处。

  • b 来看下利用抽象如何来实现多态

    还是刚才的例子,我们发现Bird这个父类,我们根本不需要使用它创建的对象,它存在的意义就是供子类来继承。所以我们可以用抽象类来优化它。

    我们把Bird父类改成抽象类,Eat()方法改成抽象方法。代码如下:
    /// <summary>
/// 鸟类:基类
/// </summary>
public abstract class Bird
{
/// <summary>
/// 吃:抽象方法
/// </summary>
public abstract void Eat();
}

Main主函数中Bird就不能创建对象了,代码稍微修改如下:

        static void Main(string[] args)
{
//创建一个Bird基类数组,添加 Magpie对象,Eagle对象,Penguin对象
Bird[] birds = {
new Magpie(),
new Eagle(),
new Penguin()
};
//遍历一下birds数组
foreach (Bird bird in birds)
{
bird.Eat();
}
Console.ReadKey();
}

由此可见,我们选择使用虚方法实现多态还是抽象类抽象方法实现多态,取决于我们是否需要使用基类实例化的对象.

  • c接口实现多态

我要问一个问题,喜鹊和老鹰都可以飞,这个飞的能力,我怎么来实现呢?

XXX答:“在父类Bird中添加一个Fly方法不就好了~~”

我再问:“好的,照你说的,企鹅继承父类Bird,但是不能企鹅不能飞啊,这样在父类Bird中添加Fly方法是不是不合适呢?”

XXX答:“那就在能飞的鸟类中分别添加Fly方法不就可以了吗?”

对,这样是可以,功能完全可以实现,可是这样违背了面向对象开放封闭原则,下次我要再扩展一个鸟类比如猫头鹰(Owl),我还要去源代码中看下Fly是怎么实现的,然后在Owl中再次添加Fly方法,相同的功能,重复的代码,这样是不合理的,程序也不便于扩展;

其次,如果我还要添加一个飞机类(Plane),我继承Bird父类,合适吗?

很显然,不合适!所以我们需要一种规则,那就是接口了,喜鹊,老鹰,飞机,我都实现这个接口,那就可以飞了,而企鹅我不实现这个接口,它就不能飞~~

好,接下来介绍一下接口如何实现多态~

添加一个接口IFlyable,代码如下:

    /// <summary>
/// 飞 接口
/// </summary>
public interface IFlyable
{
void Fly();
}

在Main主函数中,创建一个IFlyable接口数组,代码实现如下:

    static void Main(string[] args)
{
//创建一个IFlyable接口数组,添加 Magpie对象,Eagle对象
IFlyable[] flys = {
new Magpie(),
new Eagle()
};
//遍历一下flys数组
foreach (IFlyable fly in flys)
{
fly.Fly();
}
Console.ReadKey();
}

所以有人称接口让C#成为多重继承也是有一定道理的。

飞机也能飞,继承Bird不合适的问题,现在有了接口,这个问题也可以解决了。如下,我添加一个飞机Plane类,实现IFlyable接口,代码如下:

    /// <summary>
/// 飞机类,实现IFlyable接口
/// </summary>
public class Plane:IFlyable
{
/// <summary>
/// 实现接口方法
/// </summary>
public void Fly()
{
Console.WriteLine("我是一架飞机,我也能飞~~");
}
}

在Main主函数中,接口IFlyable数组,添加Plane对象:

class Program
{
static void Main(string[] args)
{
//创建一个IFlyable接口数组,添加 Magpie对象,Eagle对象,Plane对象
IFlyable[] flys = {
new Magpie(),
new Eagle(),
new Plane()
};
//遍历一下flys数组
foreach (IFlyable fly in flys)
{
fly.Fly();
}
Console.ReadKey();
}
}

(6)as 和is关键字

C# 提供 is 和 as 运算符来进行转换。可以使用这两个运算符来测试强制转换是否会成功,而没有引发异常的风险。

is 运算符检查对象是否与给定类型兼容,重点是检查,只是检查.

eg:if(b is B)将检查对象b 是否为B类型的一个实例,或者是从B派生的一个类型的实例

as 运算符用于在可兼容的引用类型之间执行类似于强制类型转换的操作,重点是操作。与强转不同的是,当转换失败时,as 运算符将返回NULL空,而不是引发异常。

(7) static void Main(string[] args)

string[]args:这是用来接收命令行传入的参数。string[]是声明args的数据类型,可以存储字符串数组。在Visual studio中,可以右键项目--属性--调试---应用程序参数来进行设置。


using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ConsoleApp
{
struct Simple
{
public int X;
public int Y;
} class SimpleClass
{
public int X;
public int Y;
}
class test { }
class Program
{ public static void Main(string[] args)
{
foreach (string s in args)
{
Console.WriteLine(s);
} } }
}

(8)不是只声明的对象不能用,是只声明的局部变量不可以用,只声明的字段如果是引用类型,那么它就是null。



如上图所示,由于在Main入口函数中,声明变量都是局部变量,所以不赋值,就不可使用,也不可拿来与null比较。

相反,在类中只声明的字段,而不赋值,那么引用类型默认就是null,值类型就是相应的默认值,如上图。

(9) 类内定义的委托和类,在外部归类所有,而非实例所有

    class test
{
public class test1 { }
public delegate void test2();
} class Program
{
public static void test3() { } public static void Main(string[] args)
{
var aa = new test();
var bb = new test.test1();
var cc = new test.test2(test3);
}

(10)重载Equals方法,与==不同的是,==对于值类型只检查是否值一样,对于引用类型,只检查引用地址是否一样。也要注意到private限定的是只有在本类内部才能被看到

    public class test
{
private int data;
public test(int data)
{
this.data = data;
}
//public bool Equals(test rhs)
//{
// return this.data == rhs.data;
//}
}
class Program
{
public static void Main()
{
var a = new test(10);
var b = new test(9);
var c = new test(10);
Console.WriteLine(a.Equals(b));
Console.WriteLine(a.Equals(c));
}
}

out:

False
False

重载Equals()方法

    public class test
{
private int data;
public test(int data)
{
this.data = data;
}
public bool Equals(test rhs)
{
return this.data == rhs.data; // data被限定为private,但在本类内部,依然可以用传过来的rhs实例来访问private data.
}
}
class Program
{
public static void Main()
{
var a = new test(10);
var b = new test(9);
var c = new test(10);
Console.WriteLine(a.Equals(b));
Console.WriteLine(a.Equals(c));
}
}

out:

False
True

(11)C#嵌套类

1.基本概念

    嵌套类:在一个类中定义另一个类,分为静态嵌套类(使用少)和非静态嵌套类(又称内部类)。 

    内部类: (1) 在一个类中直接定义类。

                (2) 在一个方法中定义类。

                (3) 匿名内部类。
  1. 嵌套类的使用

    (1)外部类只能够访问嵌套类中修饰符为public、internal的字段、方法、属性。示例如下

     public class Animal

    {

    static void Set_Animal()

    {
    //编译正确 Monkey._high = 123; Monkey._age = 4; //编译失败 Monkey._name = "hoho"; } private class Monkey {
    private static string _name; protected string _sex; internal static int _age; public static int _high; public Monkey() { } public void show() { } }

    }

(2)嵌套类可以访问外部类的方法、属性、字段而不受访问修饰符的限制

   public class Animal

{
private static int _Age; private string name; private static void DoSomething() {
Console.WriteLine(_Age); } private void DoStr() {
monkey.method(this); } /*嵌套类 定义*/ class monkey {
public static void method(Animal a) {
_Age = 23; //静态成员 a.name = "test"; //实例成员 } } }
  1. 嵌套类访问外部类实例的方法、字段、属性时候。一般在采取构造函数输入外部类

     public class Animal
{
private string _name; //*嵌套类 定义*/ class monkey {
public monkey(Animal a) {
a._name = "test"; } } }

4.继承类可以再定义一个内嵌类并从继承父类中嵌套类

 public class Animal

{
//*嵌套类 定义*/ protected class monkey {
public virtual void Method() {
Console.WriteLine("monkey"); } } } public class S_Animal : Animal {
class s_monkey :monkey {
public override void Method() {
Console.WriteLine("s_monkey"); } } }注:因为S_Animal 继承于Animal ,因此s_monkey可以继承monkey类,从而获取重写父嵌套类的机会。但是monkey必须是可继承类及可访问的(非private 、sealed、static)。 嵌套类可以随意外部类的任何数据属性,而外部类访问嵌套类就只能遵守访问修饰符。从这个角度看,嵌套类是外部类的补充,通过嵌套类可以获取更好的封装性,增加外部类的可维护性和可读性。 从程序结构看,嵌套类在逻辑上更加接近使用类。可以更有效地表示类与类之间的紧密程度。为类管理提供除命名空间外的另一种方法。 5.单例模式(singleton)就采用一种为 延迟加载初始化实例 的方法如下: public class Animal {
public Animal(){} public static Animal Intance {
get { return monkey._intance; } } class monkey {
public readonly static Animal _intance = new Animal(); } }注: 延迟加载 嵌套类的静态构造函数不会随着外部类的触发而初始化。因此可以有效地避免创建时候初始化时间,当需要使用内嵌类的时候,嵌套类才开始初始化。 6.反射内嵌类需要使用"+"而不是我们常使用的"." 。 namespace AnimalClass {
public class Animal {
public class monkey {
protected void Method() {
//do something... } } } } 注://成功 object o1 = System.Activator.CreateInstance("AnimalClass", "AnimalClass.Animal+monkey"); //失败 抛出System.TypeLoadException 异常 object o2 = System.Activator.CreateInstance("AnimalClass", "AnimalClass.Animal.monkey");

(12)null也可以进行类型转换

string s = null;
object ss = (object)s;
string sss = (string)ss;
if (sss == null) Console.WriteLine("yes");

控制台显示“yes"

C# 基础问题汇集的更多相关文章

  1. git下的团队合作模型及git基础知识汇集

    https://www.atlassian.com/git/tutorials/syncing/git-fetch Syncing svn使用单个中央库来作为开发者之间沟通的桥梁,而协同合作是通过在开 ...

  2. CSS 基础知识点 样式 选择器 伪类

    CSS 基础知识点汇集 版权声明:这篇博客是别人写的,大神博客地址 : https://www.cnblogs.com/Mtime/p/5184685.html 1.CSS 简介 CSS 指层叠样式表 ...

  3. socket和多线程编程资料汇集-基础篇

    0 基础 CS结构的分析,server端和client的选取. 1 查看端口是否链接 netstat -an|grep portid 2 root用户抓包 tcpdump port -w fn.cap ...

  4. 【JavaSE】Java基础·疑难点汇集

    Java基础·疑难点 2019-08-03  19:51:39  by冲冲 1. 部分Java关键字 instanceof:用来测试一个对象是否是指定类型的实例. native:用来声明一个方法是由与 ...

  5. java基础概念经典题目汇集

    1.下面是People和Child类的定义和构造方法,每个构造方法都输出编号.在执行new Child("mike")的时候都有哪些构造方法被顺序调用?请选择输出结果 ( ) cl ...

  6. .Net 大型分布式基础服务架构横向演变概述

    一. 业务背景 构建具备高可用,高扩展性,高性能,能承载高并发,大流量的分布式电子商务平台,支持用户,订单,采购,物流,配送,财务等多个项目的协作,便于后续运营报表,分析,便于运维及监控. 二. 基础 ...

  7. 详解Maple中的基础工具栏

    鉴于Maple 强大的符号计算功能,越来越多的人选择使用Maple 2015计算复杂的数学问题,初学者刚开始时需要对Maple有所熟悉才能很好地进行运用,下面就从基础开始,介绍Maple工作环境. M ...

  8. UML基础与Rose建模实训教程

    目  录 第1章  初识UML. 1 1.1 初识UML用例图... 1 1.2 初识UML类图... 3 第2章  Rational Rose工具... 6 2.1 安装与配置Rational Ro ...

  9. 资源 | 数十种TensorFlow实现案例汇集:代码+笔记

    选自 Github 机器之心编译 参与:吴攀.李亚洲 这是使用 TensorFlow 实现流行的机器学习算法的教程汇集.本汇集的目标是让读者可以轻松通过案例深入 TensorFlow. 这些案例适合那 ...

  10. SOA之(3)——面向服务计算基础

    面向服务计算基础(Service-Oriented Computing Fundamentals) 面向服务的计算(Service-Oriented Computing) 面向服务的计算是一个伞状术语 ...

随机推荐

  1. Hbase - hbase hbck介绍

    原文地址:https://bbs.huaweicloud.com/blogs/353332 HBaseFsck(hbck)是一种命令行工具,可检查hbase集群的region一致性和表完整性的问题,同 ...

  2. mysql : 第5章 数据库的安全性

    -- 创建用户CREATE USER utest@localhost IDENTIFIED BY 'temp';-- 查看所有用户SELECT * FROM mysql.user;-- 查看表级权限S ...

  3. jmeter 压测tcp协议

    https://www.cnblogs.com/TestSu/p/10552239.html

  4. laradock 安装扩展程序 pcntl

    起因 运行workman脚步的时候,PHP 提示缺少 pcntl 扩展 Config git:(master) php start.php -d Please install pcntl extens ...

  5. SpringBoot+使用过滤器链执行风控决策

    风控流程 下单前进行风控校验 // 1.begin---风控处理---前置处理{黑白名单校验} RiskControlRuleEnum controlRuleEnum = riskControlHan ...

  6. 爬虫管理平台-TaskPyro的任务管理

    官网:https://docs.taskpyro.cn/ 任务管理 TaskPyro提供了强大而灵活的任务管理功能,让您能够轻松创建和管理Python脚本的定时任务. 创建任务 在TaskPyro中创 ...

  7. Ubuntu更换cuda版本,gcc,g++版本

    Ubuntu更换cuda版本,gcc,g++版本 更换cuda版本 这个比较简单 可以看到 /usr/local下面有一个软链接,更换到我们需要的版本即可,cuda对应版本安装可参考官网. 创建软连接 ...

  8. SpringBoot + 布隆过滤器:亿级数据下的高效防护盾与缓存穿透实战指南

    在当今高并发.海量数据的应用场景中,布隆过滤器凭借其极低的内存占用和极快的查询效率,成为解决缓存穿透.数据预判等难题的利器.本文深度解析布隆过滤器的核心原理与实战应用,手把手教你如何将这一数据守门员融 ...

  9. Windows 鼠标右键失效

    突然有一天...小邋遢他变了... 哦不是...鼠标右键/键盘菜单键莫名其妙失效了. 解决办法 运行 regedit 打开注册表编辑器 依次展开 HKEY_CURRENT_USER\Software\ ...

  10. datasnap的Restful的接口方法

    //Restful接口测试 //GET function Test(Value: string): string; //POST function updateTest(Value: string; ...