C#中的new运算符不会覆盖基类成员

前端之家收集整理的这篇文章主要介绍了C#中的new运算符不会覆盖基类成员前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我很困惑为什么新的运算符不能像我预期的那样工作.

注意:以下所有类都在同一名称空间中定义,并在同一文件中定义.

此类允许您使用一些提供的文本为写入控制台的任何内容添加前缀.

public class ConsoleWriter
{
    private string prefix;

    public ConsoleWriter(string prefix)
    {
        this.prefix = prefix;
    }

    public void Write(string text)
    {
        Console.WriteLine(String.Concat(prefix,text));
    }
}

这是一个基类:

public class BaseClass
{
    protected static ConsoleWriter consoleWriter = new ConsoleWriter("");

    public static void Write(string text)
    {
        consoleWriter.Write(text);
    }
}

这是一个实现的类:

public class NewClass : BaseClass
{
    protected new static ConsoleWriter consoleWriter = new ConsoleWriter("> ");
}

现在这是执行此操作的代码

class Program
{
    static void Main(string[] args)
    {
        BaseClass.Write("Hello World!");
        NewClass.Write("Hello World!");

        Console.Read();
    }
}

所以我希望输出

Hello World!
> Hello World!

输出

Hello World!
Hello World!

我不明白为什么会这样.以下是关于发生的事情的思考过程:

> CLR调用BaseClass.Write()方法
> CLR初始化BaseClass.consoleWriter成员.
>使用BaseClass.consoleWriter变量调用并执行该方法

然后

> CLR调用NewClass.Write()
> CLR初始化NewClass.consoleWriter对象.
> CLR发现实现位于BaseClass中,但该方法是继承的
> CLR使用NewClass.consoleWriter变量在本地(在NewClass中)执行该方法

我认为这是继承结构的工作原理吗?

请有人帮我理解为什么这不起作用?

更新:

这种情况将如下工作(我如何实现它)

public class LogBase
{
   protected static TraceSource logger = new TraceSource("");

   public static void Error (string text) { logger.WriteError(text); }
   public static void Info (string text) { logger.WriteInformation(text); }
   public static void Warning (string text) { logger.WriteWarning(text); }
   public static void Verbose (string text) { logger.WriteVerbose(text); }
}

// DataAccess logging
public class DALog : LogBase
{
    protected new static TraceSource logger = new TraceSource("DataAccess");
}

// BusinessObjects logging
public class BOLog : LogBase
{
    protected new static TraceSource logger = new TraceSource("Objects");
}

// BusinessLogic logging
public class BLLog : LogBase
{
    protected new static TraceSource logger = new TraceSource("Logic");
}

// WebUI logging
public class WebUILog : LogBase
{
    protected new static TraceSource logger = new TraceSource("WebUI");
}

原因是我不必为每个类复制代码.

更新(选择解决方案后):

因此,为了解决这个问题,我没有使用基类,而是定义了一个功能.然后创建新类,为每个层保存Singleton实例:

public sealed class LogBase
{
   private TraceSource logger = null;

   public static LogBase GetLogger(string loggerName) 
   {
       return new LogBase(loggerName);
   }

   private LogBase(string loggerName) { logger = new TraceSource(loggerName); }

   public void Error (string text) { logger.WriteError(text); }
   public void Info (string text) { logger.WriteInformation(text); }
   public void Warning (string text) { logger.WriteWarning(text); }
   public void Verbose (string text) { logger.WriteVerbose(text); }
}

// DataAccess logging - no base class
public class DALog 
{
    private static LogBase logger;

    public static LogBase Instance
    { 
         get 
         { 
              if (logger==null) { logger = new TraceSource("DataAccess"); }
              return logger;
         }
    }
}

...

解决方法

新的运算符实际上并没有在多态性的意义上覆盖.它只是添加了另一种“发生”的方法,它具有相同的签名,但却被视为一种单独的方法.只有在子类上显式执行该方法时,才会使用“新”实现.

在您的情况下,您已在基类上实现了Write.在那里,你有调用consoleWriter的行.该行引用基类,因此使用原始实现.它甚至不知道子类中的附加实现.

检查您的代码并将其视为原样:

public class BaseClass
{
    protected static ConsoleWriter consoleWriter = new ConsoleWriter("");

    public static void Write(string text)
    {
        consoleWriter.Write(text);
    }
}


public class NewClass : BaseClass
{
    protected static ConsoleWriter anotherConsoleWriter = new ConsoleWriter(">");
}

你的BaseClass.Write不会考虑调用anotherConsoleWriter而不是consoleWriter.

如果您希望您的示例有效,您需要为Write添加一个新实现:

public class NewClass : BaseClass
{
    protected new static ConsoleWriter consoleWriter = new ConsoleWriter(">");

    public static new void Write(string text)
    {
        consoleWriter.Write(text);
    }
}

…或者,你最想要的东西,而是通过使用override而不是new来引入多态性意义上的真正覆盖.但是,您的基类需要通过将consoleWriter声明为虚拟来支持它.此外(正如您在评论中提到的),只有在您不将这些方法设为静态时,此方法才有效.

如果您仍希望静态访问记录器,则可以应用Singleton pattern,或者查看已经为您解决所有这些问题的log4net.

原文链接:https://www.f2er.com/csharp/98291.html

猜你在找的C#相关文章