经常会有人问:小伙子,有没有对象啊,要不要大叔我帮你介绍一个啊,小伙子会说:大叔,不用我自己new一个就好了。(PS:活该你没有对象)

上边当然是一个段子咯,程序员那会没有对象,自己new一个就有了啊。好了进入今天的主题 new和this的关键字。

new关键字

new 关键字可用作运算符、修饰符或约束三种用法:

1) new 运算符:用于创建对象和调用构造函数。

a)   Person person = new Person();//new是一个运算符
(1)在内存中开辟一块合适大小的空间
(2)在这个空间里创建对象
(3)调用这个对象的构造函数
(4)返回这个空间的引用地址

代码展示:

class Program
{
static void Main(string[] args)
{
Reporter rep = new Reporter("记者", 11, '男', "偷拍");
rep.SayHello();
rep.Test();
Console.ReadKey();
}
} public class Person
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private int _age;
public int Age
{
get { return _age; }
set { _age = value; }
}
private char _gender;
public char Gender
{
get { return _gender; }
set { _gender = value; }
} public Person(string name, int age, char gender)
{
this.Name = name;
this.Age = age;
this.Gender = gender;
} public void Test()
{
Console.WriteLine("测试");
} public void SayHello()
{
Console.WriteLine("大家好,我是人类");
}
} public class Reporter : Person
{
public Reporter(string name, int age, char gender, string hobby)
: base(name, age, gender)
{
this.Hobby = hobby;
} private string _hobby; public string Hobby
{
get { return _hobby; }
set { _hobby = value; }
} public void ReporterSayHello()
{
Console.WriteLine("我叫{0},我是一名狗仔,我的爱好是{1},我是{2}生,我今年{3}岁了", this.Name, this.Hobby, this.Gender, this.Age);
} public new void SayHello()
{
Console.WriteLine("大家好,我是记者");
}
}

  

2) new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。

代码展示:

public class BaseClass
{
public void functionA()
{
Console.WriteLine("BaseFunctionA http://www.cnblogs.com/sosoft/");
}
public virtual void functionB()
{
Console.WriteLine("BaseFunctionB http://www.cnblogs.com/sosoft/");
}
}
public class DerivedClass:BaseClass
{
public new void functionA()
{
Console.WriteLine("DerivedFunctionA http://www.cnblogs.com/sosoft/");
}
public override void functionB()
{
Console.WriteLine("DerivedFunctionB http://www.cnblogs.com/sosoft/");
}
} 调用:
BaseClass baseFunction=new DerivedClass();
baseFunction.functionA();
baseFunction.functionB();

运行结果:

 BaseFunctionA http://www.cnblogs.com/sosoft/

 DerivedFunctionB http://www.cnblogs.com/sosoft/

new是隐藏基类方法,override是覆写基类方法。如果要访问new隐藏了的基类成员需要使用base关键字实现。

隐藏和重写基类方法的异同:

1:方法重写:就是在基类中的方法用virtual关键字来标识,然后在继承类中对该类进行重写(override),这样基类中的方法已经被重写了,已经失去了功能了。当让基类的对象的引用直接指向继承类的对象时(多态性),调用该方法则是调用的继承类的方法。

2:方法隐藏:无论基类中的方法是否用了virtual关键字,继承类中都可以用new关键字(如果不用new的话,不会产生错误,但会生成一个编译警告)将基类中的方法隐藏,所谓隐藏就是隐藏,不像重写,重写就是原来的(基类中)已经不存在了,而隐藏是原来的还存在。所以当让基类的对象的引用直接指向继承类的对象时(多态性),调用该方法则是调用的基类的方法。

3new 约束:用于在泛型声明中约束可能用作类型参数的参数的类型。

代码展示:

class Person<T> where T : new()
{
public T GetName()
{
return new T();
}
} class Boy
{
private string _name; public string Name
{
get{return _name;}
set { _name = value; }
} public Boy()
{
_name = "feng";
}
} class Program
{
static void Main(string[] args)
{
Person<Boy> MBoy = new Person<Boy>(); Boy a = new Boy();
Console.WriteLine(a.Name); Console.WriteLine(MBoy.GetName().Name);
Console.ReadKey();
}
}

运行结果:

打印出2个"feng"

4) new 实现多态

a)  比如通过基类扩展来实现继承式多态.

b)  通过继承接口来实现多态.

代码展示:

class Num
{
public static int i = 111; public virtual void ShowClassInfo()
{
Console.WriteLine("我是基类呵呵");
}
public virtual void ShowNum()
{
Console.WriteLine("基类的数字是{0}", i.ToString());
}
} class SubNum : Num
{
new public static int i = 222; //new 作为修饰符:只是隐藏基类同名方法
public new virtual void ShowClassInfo()
{
Console.WriteLine("我是子类哈哈");
} //override则是覆写了基类的方法
public override void ShowNum()
{
Console.WriteLine("子类的数字是{0}", i.ToString());
}
} class Program
{
static void Main(string[] args)
{
Num num1 = new Num();//new 运算符用法
num1.ShowNum();
SubNum sbnum = new SubNum();
//下面2个调用的都是子类的方法 但是实现机制不一样
sbnum.ShowNum();//结果:222 sbnum.ShowClassInfo();//结果:我是子类哈哈 //new作为多态的用法:下面是典型的基类继承似多态
Num num2 = new SubNum();//num2虽然是基类的变量,但是指向了之类SubNum实例的引用 //调用方法时会在运行期检查虚拟方法表,来确定要调用的方法
num2.ShowClassInfo();//由于方法只是被隐藏了,没有被重写 所有还是调用的基类的方法 //结果:我是子类呵呵 num2.ShowNum();//方法被覆盖了 所有调用的是子类的方法 //结果: 222
Console.ReadKey();
}
}

注意:前方高能:

new关键字在我们的程序中可谓是无时不刻在用到,那么new关键字都可以用在哪些地方呢?考虑以下几个问题:
1、new一个class对象和new一个struct或者new一个enum有什么不同?
  答:new一个class时,new完成2个内容:一是调用newobj命令为实例在托管堆中分配内存,二是调用构造函数实现对象初始化。
  new一个struct时,new运算符用于调用其构造函数,完成实例的初始化。
2、new在.NET中除了创建对象实例外,还可以做什么?
  答:new关键字:作为运算符可以创建对象和调用构造函数;
  作为修饰符可以用于向基类成员隐藏继承成员,实现派生类中隐藏基类的virtual方法,不能和override共存;
  作为约束可以在泛型声明中约束可能用作类型参数的参数类型,即new约束指定泛型类声明中的任何类型参数都必须要有公共的无参构造函数;
  使用new关键字实现多态。
3、new运算符可以重载吗?
  答:new运算符不可以重载。
4、泛型中new关键字的作用?
  答:new运算符用于返回一个引用,指向系统分配的托管堆的内存地址,new分配内存失败,将引发OutOfMemoryException异常。
5、new一个继承下来的方法和override有什么区别?
  答:new是隐藏基类方法,override是覆写基类方法。如果要访问new隐藏了的基类成员需要使用base关键字实现。
6、int i和int i = new int()有什么不同?
  答:new一个int时,new运算符用于初始化其值为0,使构造函数完成更优越的初始化操作。

 

this关键字

1)、代表当前类的对象

代码展示:

class MyClass
{
// 声明一个名为"myVal"的整型字段
public int myVal = 10; // 声明一个构造函数,该函数带一个名为"myVal"的参数
public MyClass(int myVal)
{
// "this"表示MyClass类的当前实例
// 在这里通过this可以在语义上区分成员名myVal和参数名myVal
this.myVal += myVal; // 使用this作为当前对象的实参传递给Compute方法
int res = myVal + MyClass1.Compute(this);
}
}

  

2)、在类当中显示的调用本类的构造函数  :this

代码展示:

class MyClass
{
// 声明一个名为"myVal"的整型字段
public int myVal = 10; // 声明一个构造函数,该函数带一个名为"myVal"的参数
public MyClass(int myVal)
{
// "this"表示MyClass类的当前实例
// 在这里通过this可以在语义上区分成员名myVal和参数名myVal
this.myVal += myVal;
}
}

  

3)、声明索引器。(PS:这个会在后续的博客中更新)

代码展示:

 /// <summary>
///
/// </summary>
public NameValueCollection Attr = new NameValueCollection(); /// <summary>
/// /*************************/
/// /* this用法3:声明索引器 */
/// /*************************/
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string this[string key]
{
set
{
Attr[key] = value;
} get
{
return Attr[key];
}
}

4)、扩展对象的方法

代码展示:

/// <summary>
///Person 的摘要说明
/// </summary>
public class Person
{  /// <summary>
/// 性别
/// </summary>
public string Sex { set; get; }
} /// <summary>
/// 辅助类
/// </summary>
public static class Helper
{ /// <summary>
/// /*****************************/
/// /* this用法4:扩展对象的方法 */
/// /*****************************/
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public static string GetSex(this Person item)
{
return item.Sex;
}
}
调用: Person person = new Person();
person.GetSex();

  

本篇就到这里了,最后打个小广告:QQ群: .NET 一步步一幕幕  群号:590170361 (加群备注:博客园看到的)

.NET 基础 一步步 一幕幕[面向对象之new、this关键字]的更多相关文章

  1. .NET 基础一步步一幕幕[面向对象前言]

    面向对象前言 2017年的第一篇博文,好久不写博文了,赶紧补上,感觉在以前的<.NET 基础一步步一幕幕>系列博客中,简短的小知识点已经介绍的差不多的(PS:如果还有别的基础知识点我没有介 ...

  2. .NET 基础 一步步 一幕幕[面向对象之对象和类]

    对象和类 本篇正式进入面向对象的知识点简述: 何为对象,佛曰:一花一世界,一木一浮生,一草一天堂,一叶一如来,一砂一极乐,一方一净土,一笑一尘缘,一念一清静.可见"万物皆对象". ...

  3. .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]

    方法.方法的重载.方法的重写.方法的递归 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值 ...

  4. .NET 基础 一步步 一幕幕[面向对象之构造函数、析构函数]

    构造函数.析构函数 构造函数: 语法: //无参的构造函数 [访问修饰符] 函数名() :函数名必须与类名相同. //有参的构造函数 [访问修饰符] 函数名(参数列表):函数名必须与类名相同. 作用: ...

  5. .NET 基础 一步步 一幕幕[面向对象之静态、非静态]

    静态.非静态 先来看一段代码来区分静态与非静态: using System; using System.Collections.Generic; using System.Linq; using Sy ...

  6. .NET 基础 一步步 一幕幕[面向对象之堆、栈、引用类型、值类型]

    堆.栈.引用类型.值类型 内存分为堆和栈(PS:还有一种是静态存储区域 [内存分为这三种]),值类型的数据存储在栈中,引用类型的数据存储在堆中. 堆.栈: 堆和栈的区别: 栈是编译期间就分配好的内存空 ...

  7. .NET 基础 一步步 一幕幕 [前言]

    .NET 基础 一步步 一幕幕 [前言部分] 本人小白一枚,虽然说从去年就开通博客了,到现在也没有写多少东东,虽然工作了,也没有更好得总结.故此重新祭出博客园法宝,修炼技术,争取早日走上大神之位. 故 ...

  8. .NET基础 一步步 一幕幕[循环、逻辑语句块]

    循环.逻辑语句块   好久不写博客了,断更了好几天了,从上周五到今天,从北京到上海,跨越了1213.0公里,从一个熟悉的城市到陌生的城市,还好本人适应力比较好,还有感谢小伙伴的接风咯,一切都不是事,好 ...

  9. .NET 基础 一步步 一幕幕 [.NET 简介]

    .NET 简介 .NET是 Microsoft XML Web services 平台.是微软用来实现XML,Web Services,SOA(面向服务的体系结构service-oriented ar ...

随机推荐

  1. WPF DataBinding之我见

    原创,转载请注明出处:WPF DataBinding之我见 一.DataBinding介绍   数据绑定是在应用程序 UI 与业务逻辑之间建立连接的过程. 如果绑定具有正确设置并且数据提供正确通知,则 ...

  2. C++序列化库的实现

    C++中经常需要用到序列化与反序列化功能,由于C++标准中没有提供此功能,于是就出现了各式各样的序列化库,如boost中的,如谷歌的开源项目,但是很多库都依赖其他库过于严重,导致库变得很庞大.今天来分 ...

  3. SGU 137.Funny String

    题目描述 一个序列S1 S2 S3... Sn 如果满足 新序列 S1-1 S2 S3 ...Sn+1能够通过旋转的操作(不是翻转)来得到旧的序列,那么这个序列就叫做Funny序列.例如 1 2 1 ...

  4. java.math.BigDecimal类

    BigDecimal类用于高精度计算.一般的float型和Double型数据只可以用来做科学计算或者是工程计算,由于在商业计算中,要求的数字精度比较高,所以要用到java.math.BigDecima ...

  5. 关于javascript输出中文乱码的问题

    今天找到一个引导效果.原来是用英文进行引导.但是我改了里面的英文为汉字就出现乱码的情况.英文提示是在js页面里面完成的.所以最后的解决办法 就是把js文件用记事本打开,然后把文件另存为utf-8的格式 ...

  6. 【技术宅6】把一个无限级分类循环成tree结构

    function list_to_tree($list,$root=0,$pk='cid',$pid = 'pid',$child = '_child'){ if(is_array($list)) { ...

  7. yii 验证确认密码是否一致 【"compare",'compareAttribute'=>'password'】

    array("surepassword","compare",'compareAttribute'=>'password','message'=>' ...

  8. Android SlidingMenu开源库及其使用

    极客学院教程: http://www.jikexueyuan.com/course/61_5.html?ss=1 1. SlidingMenu开源库的配置 2. SlidingMenu 的使用 --- ...

  9. 如何在search中动态的显示和隐藏tree中的字段

    在tree定义 invisible 来自context <field name="country_id" invisible="context.get('invis ...

  10. ubuntu下使用C语言开发一个cgi程序

    主要步骤是: 1. 开发一个C程序(在标准输出中输出HTML字符串) 2. 复制到apache2的cgi-bin目录去 3. 在httpd.conf中开启cgi功能(我似乎没用到,也可以使用cgi) ...