前几天去家公司面试,有一道这样的题:写出c#中new关键字的三种用法,思前想后挖空心思也只想出了两种用法,回来查了下msdn,还真是有第三种用法:用于在泛型声明中约束可能用作类型参数的参数的类型,这是在Framework 2.0 中定义泛行时才会使用到的,自己对c# 2.0 中的支持还只是粗通皮毛,怪不得累死so many脑细胞也没能想不出这第三种来!

 
三种用法如下:
在 C# 中,new 关键字可用作运算符、修饰符或约束。
1)new 运算符:用于创建对象和调用构造函数。这种大家都比较熟悉,没什么好说的了。
2)new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。
3)new 约束:用于在泛型声明中约束可能用作类型参数的参数的类型。 
 
关于第二种用法看下例:
using System;
namespace ConsoleApplication1
{
    public class BaseA
    {
        public int x = 1;
        public void Invoke()
        {
            Console.WriteLine(x.ToString());
        }
        public int TrueValue
        {
            get { return x; }
            set { x = value; }
        }
    }
    public class DerivedB : BaseA
    {
        new public int x = 2;
        new public void Invoke()
        {
            Console.WriteLine(x.ToString());
        }
        new public int TrueValue
        {
            get { return x; }
            set { x = value; }
        }
    }
 
    class Test
    {
        static void Main(string[] args)
        {
            DerivedB b = new DerivedB();
            b.Invoke();//调用DerivedB的Invoke方法,输出:2
            Console.WriteLine(b.x.ToString());//输出DerivedB的成员x值:2
            BaseA a = b;
            a.Invoke();//调用BaseA的Invoke方法,输出:1
            a.TrueValue = 3;//调用BaseA的属性TrueValue,修改BaseA的成员x的值
            Console.WriteLine(a.x.ToString());//输出BaseA的成员x的值:3
            Console.WriteLine(b.TrueValue.ToString());//输出DerivedB的成员x的值,仍然是:1
//可见,要想访问被隐藏的基类的成员变量、属性或方法,办法就是将子类造型为父类,然
//后通过基类访问被隐藏的成员变量、属性或方法。
        }
     }
}
 
new约束指定泛型类声明中的任何类型参数都必须具有公共的无参数构造函数.请看下例:
using System;
using System.Collections.Generic;
 
namespace ConsoleApplication2
{
    public class Employee
    {
        private string name;
        private int id;
 
        public Employee()
        {
            name = "Temp";
            id = 0;
        }
 
        public Employee(string s, int i)
        {
            name = s;
            id = i;
        }
 
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
 
        public int ID
        {
            get { return id; }
            set { id = value; }
        }
    }
 
    class ItemFactory<T> where T : new()
    {
        public T GetNewItem()
        {
            return new T();
        }
    }
 
    public class Test
    {
        public static void Main()
        {
            ItemFactory<Employee> EmployeeFactory = new ItemFactory<Employee>();
            ////此处编译器会检查Employee是否具有公有的无参构造函数。
            //若没有则会有The Employee must have a public parameterless constructor 错误。
            Console.WriteLine("{0}'ID is {1}.", EmployeeFactory.GetNewItem().Name, EmployeeFactory.GetNewItem().ID);
        }
    }
}
 
 
见MSDN上关于New的解释

new 修饰符(C# 参考)

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

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

public class BaseC

{

    public int x;

    public void Invoke() { }

}
public class DerivedC : BaseC

{

    new public void Invoke() { }

}

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

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

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

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

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

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

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

示例

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

public class BaseC

{

    public static int x = 55;

    public static int y = 22;

}

public class DerivedC : BaseC

{

    // Hide field 'x'.

    new public static int x = 100;

    static void Main()

    {

        // Display the new value of x:

        Console.WriteLine(x);

        // Display the hidden value of x:

        Console.WriteLine(BaseC.x);

        // Display the unhidden member y:

        Console.WriteLine(y);

    }

}
/*

Output:

100

55

22

*/

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

 public class BaseC 

{

    public class NestedC 

    {

        public int x = 200;

        public int y;

    }

}

public class DerivedC : BaseC { // Nested type hiding the base type members.

    new public class NestedC   

    {

        public int x = 100;

        public int y; 

        public int z;

    }

    static void Main() 

    {

        // Creating an object from the overlapping class:

        NestedC c1  = new NestedC();

        // Creating an object from the hidden class:

        BaseC.NestedC c2 = new BaseC.NestedC();

        Console.WriteLine(c1.x);

        Console.WriteLine(c2.x);   

    }

}
/*

Output:

100

200

*/

如果移除 new 修饰符,该程序仍可编译和运行,但您会收到以下警告:

The keyword new is required on 'MyDerivedC.x' because it hides inherited member 'MyBaseC.x'.

c# new三种用法的更多相关文章

  1. using 的三种用法

    using 有哪三种用法? 1)引入命名空间. 2)给命名空间或者类型起别名. 3)划定作用域.自动释放资源,使用该方法的类型必须实现了 System.IDisposable接口,当对象脱离作用域之后 ...

  2. Js闭包常见三种用法

        Js闭包特性源于内部函数可以将外部函数的活动对象保存在自己的作用域链上,所以使内部函数的可以将外部函数的活动对象占为己有,可以在外部函数销毁时依然存有外部函数内的活动对象内容,这样做的好处是可 ...

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

    前几天去家公司面试,有一道这样的题:写出c#中new关键字的三种用法,思前想后挖空心思也只想出了两种用法,回来查了下msdn,还真是有第三种用法:用于在泛型声明中约束可能用作类型参数的参数的类型,这是 ...

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

    SQL.LINQ.Lambda 三种用法颜色注释: SQL LinqToSql Lambda QA1. 查询Student表中的所有记录的Sname.Ssex和Class列.select sname, ...

  5. c# new关键字的三种用法

    三种用法如下: 在 C# 中,new 关键字可用作运算符.修饰符或约束. 1)new 运算符:用于创建对象和调用构造函数. 2)new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成 ...

  6. java中 this 的三种用法

    Java中this的三种用法 调用属性 (1)this可以调用本类中的任何成员变量 调用方法(可省略) (2)this调用本类中的成员方法(在main方法里面没有办法通过this调用) 调用构造方法 ...

  7. 子查询。ANY三种用法。ALL两种用法。HAVING中使用子查询。SELECT中使用子查询。

    子查询存在的意义是解决多表查询带来的性能问题. 子查询返回单行多列: ANY三种用法: ALL两种用法: HAVING中的子查询返回单行单列: SELECT中使用子查询:(了解就好,避免使用这种方法! ...

  8. java中 this 关键字的三种用法

    Java中this的三种用法 调用属性 (1)this可以调用本类中的任何成员变量 调用方法(可省略) (2)this调用本类中的成员方法(在main方法里面没有办法通过this调用) 调用构造方法 ...

  9. C++学习---- virtual的三种用法

    virtual用法一:多态 #include<iostream> using namespace std; class A{ public: virtual void display(){ ...

随机推荐

  1. python cookbook第三版学习笔记三:列表以及字符串

    过滤序列元素: 有一个序列,想从其中过滤出想要的元素.最常用的办法就是列表过滤:比如下面的形式:这个表达式的意义是从1000个随机数中选出大于400的数据 test=[] for i in range ...

  2. oracle 11g ocr 冗余配置

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/royjj/article/details/30506343  oracle 11g ocr 冗余 ...

  3. python中的编码转换

    今天遇到了一个问题,将字符串“\uxxxx\uxxxx”转换成汉字.网上查了很多资料都不行. 后来看到,发现一个函数就OK了. str = str.decode('unicode_escape') 等 ...

  4. hdu1015 —— 回溯

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1015 因为之前看了下刘汝佳的<算法入门经典>,就用类似打印全排列,八皇后的方法做.本以为不 ...

  5. ffmpeg 调试

    --enable-debug=3 --disable-optimizations --disable-yasm --disable-asm

  6. Android SDK中 tools 目录下的工具介绍

    Android SDK包含了各种各样的定制工具,简介如下: Android模拟器(Android Emulator )它是在你的计算机上运行的一个虚拟移动设备.你可以使用模拟器来在一个实际的Andro ...

  7. BZOJ 1614 [Usaco2007 Jan]Telephone Lines架设电话线:spfa + 二分【路径中最大边长最小】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1614 题意: 给你一个无向图,n个点,m条边. 你需要找出一条从1到n的路径,使得这条路径 ...

  8. 【HDU2050】折线分割平面

    Position Solution 2×n^2-n+1 证明见分割问题 Code // This file is made by YJinpeng,created by XuYike's black ...

  9. bzoj 3685

    线段树 方法一: 值域线段树,递归去写的,每次节点存出现次数. 对于几个操作, 1,2 直接加减就好 ; 3,4 操作贪心往某一个方向找 .7也很简单,主要说前驱后继怎么找.我是先找这个数第几小,根据 ...

  10. JDK中主要的包介绍