NEW关键字的三种用法

声明:本文最初是本人从他出转载到51CTO上的一篇文章,但现在记不清最初从出处了,原文作者看到还请原来,现在发表在这里只为学习,本人在51CTO的该文章的地址为:http://kestrelsaga.blog.51cto.com/3015222/751536

一、             new运算符

①     用于创建对象和调用构造函数。 例如:

  1. Class1 obj  = new Class1();

②     还可用于创建匿名类型的实例:

  1. var query = from cust in customers
  2. select new {Name = cust.Name, Address = cust.PrimaryAddress};

③     new 运算符还用于调用值类型的默认构造函数。 例如:

  1. int i = new int();

在上一个语句中,i 初始化为 0,它是 int 类型的默认值。 该语句的效果等同于:

  1. int i = 0;

请记住,为结构声明默认的构造函数是错误的,因为每一个值类型都隐式具有一个公共的默认构造函数。 可以在结构类型上声明参数化构造函数以设置其初始值,但是,只有在需要默认值之外的值时才必须这样做。

值类型对象(例如结构)是在堆栈上创建的,而引用类型对象(例如类)是在堆上创建的。 两种类型的对象都是自动销毁的,但是,基于值类型的对象是在超出范围时销毁,而基于引用类型的对象则是在对该对象的最后一个引用被移除之后在某个不确定的时间销毁。 对于占用固定资源(例如大量内存、文件句柄或网络连接)的引用类型,有时需要使用确定性终止以确保对象被尽快销毁。

不能重载 new 运算符。

如果 new 运算符分配内存失败,将引发异常 OutOfMemoryException

示例

在下面的示例中,通过使用 new 运算符创建并初始化一个 struct 对象和一个类对象,然后为它们赋值。 显示了默认值和所赋的值。

  1. struct SampleStruct
  2. {
  3. public int x;
  4. public int y;
  5. public SampleStruct(int x, int y)
  6. {
  7. this.x = x;
  8. this.y = y;
  9. }
  10. }
  11. class SampleClass
  12. {
  13. public string name;
  14. public int id;
  15. public SampleClass() {}
  16. public SampleClass(int id, string name)
  17. {
  18. this.id = id;
  19. this.name = name;
  20. }
  21. }
  22. class ProgramClass
  23. {
  24. static void Main()
  25. {
  26. // Create objects using default constructors:
  27. SampleStruct Location1 = new SampleStruct();
  28. SampleClass Employee1 = new SampleClass();
  29. // Display values:
  30. Console.WriteLine("Default values:");
  31. Console.WriteLine("   Struct members: {0}, {1}",
  32. Location1.x, Location1.y);
  33. Console.WriteLine("   Class members: {0}, {1}",
  34. Employee1.name, Employee1.id);
  35. // Create objects using parameterized constructors:
  36. SampleStruct Location2 = new SampleStruct(10, 20);
  37. SampleClass Employee2 = new SampleClass(1234, "Cristina Potra");
  38. // Display values:
  39. Console.WriteLine("Assigned values:");
  40. Console.WriteLine("   Struct members: {0}, {1}",
  41. Location2.x, Location2.y);
  42. Console.WriteLine("   Class members: {0}, {1}",
  43. Employee2.name, Employee2.id);
  44. }
  45. }
  46. /*
  47. Output:
  48. Default values:
  49. Struct members: 0, 0
  50. Class members: , 0
  51. Assigned values:
  52. Struct members: 10, 20
  53. Class members: Cristina Potra, 1234
  54. */

注意,在示例中字符串的默认值为 null 因此未显示它。

二、             new修饰符

在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。 隐藏继承的成员时,该成员的派生版本将替换基类版本。 虽然可以在不使用 new 修饰符的情况下隐藏成员,但会生成警告。 如果使用 new 显式隐藏成员,则会取消此警告,并记录要替换为派生版本这一事实。

若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并使用 new 修饰符修饰该成员。 例如:

  1. public class BaseC
  2. {
  3. public int x;
  4. public void Invoke() { }
  5. }
  6. public class DerivedC : BaseC
  7. {
  8. new public void Invoke() { }
  9. }

在此示例中,DerivedC.Invoke 隐藏了 BaseC.Invoke。 字段 x 不受影响,因为它没有被类似名称的字段隐藏。

通过继承隐藏名称采用下列形式之一:

·             引入类或结构中的常数、指定、属性或类型隐藏具有相同名称的所有基类成员。

·             引入类或结构中的方法隐藏基类中具有相同名称的属性、字段和类型。 同时也隐藏具有相同签名的所有基类方法。

·             引入类或结构中的索引器将隐藏具有相同名称的所有基类索引器。

对同一成员同时使用 new 和 override 是错误的做法,因为这两个修饰符的含义互斥。 new 修饰符会用同样的名称创建一个新成员并使原始成员变为隐藏的。 override 修饰符会扩展继承成员的实现。

在不隐藏继承成员的声明中使用 new 修饰符将会生成警告。

示例

在该例中,基类 BaseC 和派生类 DerivedC 使用相同的字段名 x,从而隐藏了继承字段的值。 该示例演示了 new 修饰符的用法。 另外还演示了如何使用完全限定名访问基类的隐藏成员。见:

  1. public class BaseC
  2. {
  3. public static int x = 55;
  4. public static int y = 22;
  5. }
  6. public class DerivedC : BaseC
  7. {
  8. // Hide field ‘x‘.
  9. new public static int x = 100;
  10. static void Main()
  11. {
  12. // Display the new value of x:
  13. Console.WriteLine(x);
  14. // Display the hidden value of x:
  15. Console.WriteLine(BaseC.x);
  16. // Display the unhidden member y:
  17. Console.WriteLine(y);
  18. }
  19. }
  20. /*
  21. Output:
  22. 100
  23. 55
  24. 22
  25. */

在此示例中,嵌套类隐藏了基类中同名的类。 此示例演示了如何使用 new 修饰符来消除警告消息,以及如何使用完全限定名来访问隐藏的类成员。见:

  1. public class BaseC
  2. {
  3. public class NestedC
  4. {
  5. public int x = 200;
  6. public int y;
  7. }
  8. }
  9. public class DerivedC : BaseC
  10. {
  11. // Nested type hiding the base type members.
  12. new public class NestedC
  13. {
  14. public int x = 100;
  15. public int y;
  16. public int z;
  17. }
  18. static void Main()
  19. {
  20. // Creating an object from the overlapping class:
  21. NestedC c1  = new NestedC();
  22. // Creating an object from the hidden class:
  23. BaseC.NestedC c2 = new BaseC.NestedC();
  24. Console.WriteLine(c1.x);
  25. Console.WriteLine(c2.x);
  26. }
  27. }
  28. /*
  29. Output:
  30. 100
  31. 200
  32. */

如果移除 new 修饰符,该程序仍可编译和运行,但您会收到以下警告:The keyword new is required on ‘MyDerivedC.x‘ because it hides inherited member ‘MyBaseC.x‘.

三、             new约束

new 约束指定泛型类声明中的任何类型参数都必须有公共的无参数构造函数。 如果要使用 new 约束,则该类型不能为抽象类型。

示例

当泛型类创建类型的新实例,请将 new 约束应用于类型参数,如下面的示例所示:

  1. class ItemFactory<T> where T : new()
  2. {
  3. public T GetNewItem()
  4. {
  5. return new T();
  6. }
  7. }

当与其他约束一起使用时,new() 约束必须最后指定:

  1. public class ItemFactory2<T>
  2. where T : IComparable, new()
  3. {
  4. }
时间: 2024-10-10 15:52:33

NEW关键字的三种用法的相关文章

.NET(c#)new关键字的三种用法

前几天去家公司面试,有一道这样的题:写出c#中new关键字的三种用法,思前想后挖空心思也只想出了两种用法,回来查了下msdn,还真是有第三种用法:用于在泛型声明中约束可能用作类型参数的参数的类型,这是在Framework 2.0 中定义泛行时才会使用到的,自己对c# 2.0 中的支持还只是粗通皮毛,怪不得累死so many脑细胞也没能想不出这第三种来! 三种用法如下: 在 C# 中,new 关键字可用作运算符.修饰符或约束. 1)new 运算符:用于创建对象和调用构造函数.这种大家都比较熟悉,没

this和super关键字的常见三种用法

super和this的含义 super :代表父类的存储空间标识(可以理解为父亲的引用). this :代表当前对象的引用(谁调用就代表谁). super关键字的三种用法: 在子类的成员方法中,访问父类的成员变量格式:super.成员变量名: 在子类的成员方法中,访问父类的成员方法格式:super.方法变量名: 在子类的构造方法中,访问父类的构造方法格式:super(): this关键字的三种用法: 在本类成员方法中,访问本类的成员变量格式:this.变量名 在本类成员方法中,访问本类的另一个成

c# new的三种用法

在 C# 中,new 关键字可用作运算符.修饰符或约束. 1)new 运算符:用于创建对象和调用构造函数.这种大家都比较熟悉,没什么好说的了. 2)new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员. 3)new 约束:用于在泛型声明中约束可能用作类型参数的参数的类型. 东西不用就会忘c# new的三种用法,布布扣,bubuko.com

指针与引用的区别以及引用的三种用法

1.指针与引用的区别: 指针是一块内存的地址值,而引用是一块内存的别名. 下面引自:http://www.cnblogs.com/kingln/articles/1129114.html 从概念上讲.指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变. 而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一

java中 this 的三种用法

Java中this的三种用法 调用属性 (1)this可以调用本类中的任何成员变量 调用方法(可省略) (2)this调用本类中的成员方法(在main方法里面没有办法通过this调用) 调用构造方法 (3)this调用构造方法只能在本构造方法中调用另一个构造方法(4)this 调用构造方法必须写在第一行 eg: 1 public class ThisDemo { 2 private int id; 3 private String name; 4 public ThisDemo(){ //(1)

SQL、LINQ、Lambda 三种用法(转)

SQL.LINQ.Lambda 三种用法 颜色注释: SQL LinqToSql Lambda QA 1. 查询Student表中的所有记录的Sname.Ssex和Class列. select sname,ssex,class from student Linq: from s in Students select new { s.SNAME, s.SSEX, s.CLASS } Lambda: Students.Select( s => new { SNAME = s.SNAME,SSEX =

SQL、LINQ、Lambda 三种用法互换

SQL.LINQ.Lambda 三种用法颜色注释: SQL LinqToSql Lambda QA1. 查询Student表中的所有记录的Sname.Ssex和Class列.select sname,ssex,class from studentLinq: from s in Students select new { s.SNAME, s.SSEX, s.CLASS }Lambda: Students.Select( s => new { SNAME = s.SNAME,SSEX = s.SS

同一个关键字,三种匹配方式投放的问题

同一个关键字,用3种匹配方式投放,调整出价的时候应该怎么调整. 一般情况下,这三种匹配方式指的是精确匹配,词组匹配和广泛匹配.为什么要有这三种匹配方式? 个人感觉原因就是你发现有一个词是自己产品的很准确的关键词,当你添加到账户之后,运用某种匹配方式,如词组匹配,运行一段时间,发现展示量很少,CTR很低,这时候,你会考虑是否要更改匹配方式,如更改成广泛匹配,但更改的同时你不知道会带来怎么样的后果,所以就直接在原账户里添加一个广泛匹配和精确匹配(即完全匹配),如[A],"A",A然后从搜索

yield关键字详解与三种用法

本篇文章比较硬核, 适合有一定Python基础的读者阅读, 如果您对Python还不甚了解可以先关注我哦, 我会持续更新Python技术文章 yield详解 yield与return相同每次调用都会返回一个值, 不同的是return返回值后会直接结束函数执行, 而yeild则是返回值后冻结函数执行, 下次调用此函数会从冻结处开始执行 (冻结就是保存函数状态, 所有的局部变量与执行状态都会被保留) yield语法 send参数 yield 返回值 语法分为三个部分, 除yield关键字外其它两个部