【问题标题】:String is not being assigned?没有分配字符串?
【发布时间】:2015-04-16 05:21:24
【问题描述】:
using System;

public class Shurli
{
    public class MyTest
    {
        private string name = "qwe";   // the name field
        public string Name   // the Name property
        {
            get
            {
                return this.name;
            }
        }
    }

    public class yourJs : MyTest
    {
        private string name = "chah";
    }

    static void Main()
    {
        var met = new yourJs();

        string acer = met.Name;
        Console.WriteLine(acer);
    }
}

我完全期望输出是“chah”,但输出是“qwe”。几个小时前我一直在尝试解决这个问题,但仍然没有弄清楚。有人可以帮忙吗?

Visual Studio 发出警告:“字段 'Shurli.yourJs.name' 已分配,但其值从未使用过”

【问题讨论】:

  • 尝试设置断点?
  • 您已将 yourJS.name 添加为私有 ..
  • 当met.Name被调用时,this.name不应该引用met.name吗? met 是从类 yourJs 实例化的对象,yourJs 包含代码private string name = "chah";。那么 met.name 不应该评估为“chah”吗?
  • @bit MyTest.name 也是私有的

标签: c# variables inheritance variable-assignment


【解决方案1】:

MyTestyourJs 类中的 name 字段位于两个不同的范围内 - 尽管它们具有相同的名称,但它们彼此完全独立。

为了使代码按照您描述的方式工作,name 应仅在基类中声明为 protected 字段,然后在子类中分配。

public class MyTest
{
    protected string name = "qwe";   // the name field
    public string Name   // the Name property
    {
        get
        {
            return this.name;
        }
    }
}

public class yourJs : MyTest
{
    public yourJs()
    {
        name = "chah";
    }
}

【讨论】:

  • @discussedtree private 表示唯一声明该类的类可以访问它。
  • 当met.Name被调用时,this.name不应该引用met.name吗? met 是从类 yourJs 实例化的对象,yourJs 包含代码private string name = "chah";。那么 met.name 不应该评估为“chah”吗?
  • @discussedtree 该对象有 两个 name 字段,每个字段都有不同的值。该方法范围内的name 变量具有被打印的值。另一个(在您的情况下是不可访问和未使用的)字段具有其他值。
【解决方案2】:

met.Name 将引用 MyTest 中的继承属性,因为 yourJs 仅包含 name,它是私有成员,无法在类外访问定向表单。请记住,C# 区分大小写,nameName 是两个不同的变量。

如果您想访问 yourJs name 私有数据成员,那么您需要将其设为公共或访问其值到某个公共方法/属性。

只是为了检查您是否可以在yourJs 中访问成员name,我们将其公开。

public class yourJs : MyTest
{
    public string name = "chah";
}

static void Main()
{
    var met = new yourJs();

    string acer = met.name;
    Console.WriteLine(acer);
}

编辑基于cmets,关于私有成员和公共属性的关系。

Properties

属性是提供灵活读取机制的成员, 写入或计算私有字段的值。可以使用属性 好像它们是公共数据成员,但它们实际上是特殊的 称为访问器的方法。这样可以轻松访问数据,并且 仍然有助于提高方法的安全性和灵活性。

【讨论】:

  • 那么为什么met.Name 指的是MyTest.name? MyTest.name 也是私有的
  • met.Name 是一个公共属性,可以从类外部访问。由于此公共属性是您的 MyTest 类的一部分,因此它可以访问 MyTest 的私有成员,即名称,这将有助于您理解这一点,msdn.microsoft.com/en-us/library/x9fsa0sw.aspx
  • 调用met.Name时,this.name不应该引用met.name吗?
  • met 是你指的对象,所以 this 指的是met。如果你改变返回 this.name;返回名称;你会得到同样的结果。
  • met 是从类 yourJs 实例化的对象,yourJs 包含代码 private string name = "chah";。那么 met.name 不应该评估为“chah”吗?
【解决方案3】:

在内存中,yourJs 对象将具有一个 Name 属性和两个名为 name 的实例字段(一个继承自它的基类 MyTest,另一个在 派生类本身)。

  • 在派生类型中声明的字段name隐藏继承的字段。
  • 继承的属性Name始终引用继承的字段name,无论您对字段使用什么访问修饰符。

您可以通过三个选项来获得所需的输出:

选项 1:正如 BJ Myers 所说,name 字段应仅在基类中声明,然后在派生类中分配。

方案二:在派生类中声明一个同名的新属性(隐藏继承的属性)。

public class MyTest
{
    private string name = "qwe";
    public string Name { get { return name; } }
}

public class yourJs : MyTest
{
    private string name = "chah";
    public new string Name { get { return name; } }
}

选项 3:覆盖继承的属性以使用派生类中声明的字段。

public class MyTest
{
    private string name = "qwe";
    public virtual string Name { get { return name; } }
}

public class yourJs : MyTest
{
    private string name = "chah";
    public override string Name { get { return name; } }
}

【讨论】:

  • "无论您对字段使用什么访问修饰符,继承的属性 Name 将始终引用继承的字段名称。"为什么?是不是因为继承的字段的作用域优先于新定义的字段?
  • 这是 CLR 处理成员继承的方式,这完全有道理,你不希望继承的 function member 在派生类中产生不同的结果,除非你明确覆盖它。看看这个问题:How does CLR organize memory/reference during the inheritance?
【解决方案4】:

private string name = "chah"; 将在yourJs 类中声明一个new 字段。
因此,您有 两个 字段称为 name - 一个位于 MyTest 中,一个位于 yourJs 中。

AND:属性Name 返回字段MyTest.name,因为NameMyTest 中声明。

这与 private 修饰符无关 - 问题是引入了第二个 name 字段。

如果你想改变yourJsname的值,你必须声明它不同:

public class MyTest {
    protected string name = "qwe";   // This is the ONLY name field, visible by inherited classes

    public string Name {
        get { return this.name; }
    }
}

public class yourJs: MyTest {
    public yourJs() {
        name = "chah";              // Change the value of MyTest.name
        base.name = "chah";         // Same as above, but explicit useage of base class MyTest
    }
}

【讨论】:

  • 当met.Name被调用时,this.name不应该引用met.name吗? met 是从类 yourJs 实例化的对象,yourJs 包含代码private string name = "chah";。那么 met.name 不应该评估为“chah”吗?
  • 不是,因为this的范围是MyTest的属性getter。所以this.name 指的是MyTest 的字段。而且,MyTest 中的所有内容都不知道 yourJs 的任何内容。
  • MyTestyourJs 继承
  • 没错。我认为这让您感到困惑,因为您给两个字段都赋予了相同的名称name。例如,您可以轻松地将字段 yourJs.name 重命名为 yourJs.name2 - 您的运行代码不会有任何区别。
  • "AND:属性名称返回字段 MyTest.name" - 但为什么呢?我正在调用met.nameMyTest 方法,它是从类yourJs 实例化的。不应该参考yourJsMyTest方法吗?
猜你喜欢
  • 2021-10-07
  • 2012-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-29
  • 1970-01-01
  • 2023-03-08
相关资源
最近更新 更多