【问题标题】:Can one change the instance of an object with the member function of its class?可以使用类的成员函数更改对象的实例吗?
【发布时间】:2019-01-21 13:06:33
【问题描述】:

一个成员函数应该改变调用对象的实例。但我最近的尝试并没有改变实例。

我想提供一个基类,它实现了一个将字符串(或文件)反序列化为子类对象的函数。

我试图实现一个扩展方法,但它没有按预期工作。调用实例不会改变。 类子类:基类 { [XmlAttribute(AttributeName = "属性")] 公共字符串属性{集;得到; } } 类基类 {} 类静态 BaseClassExtension { public static void Deserialize(this BaseClass bar, string filePath) { 使用 (StreamReader reader = new StreamReader(filePath)) { XmlSerializer 序列化器 = new XmlSerializer(obj.GetType()); bar = (BaseClass)serializer.Deserialize(reader); } } } 课堂节目 { 公共无效主要() { ChildClass foo = new ChildClass(); foo.Deserialize("file.xml") } } 在 foo.Deserialize() 中,对象“bar”被填充,但函数结束后,foo 仍然是“空”的 new ChildClass(),并且没有 bar 的内容。

这样的事情有可能吗?

编辑: 好的,让我们忘记扩展方法。另一种尝试是:

class ChildClass : BaseClass
{
    [XmlAttribute(AttributeName = "atribute")]
    public string Atribute { set; get; }
}

class BaseClass
{
    public void Deserialize(string filePath)
    {
        using (StreamReader reader = new StreamReader(filePath))
        {
            XmlSerializer serializer = new XmlSerializer(this.GetType());
            return (BaseClass)serializer.Deserialize(reader);
        }
    }
}

class Program
{
    public void Main()
    {
        ChildClass foo = new ChildClass();

        // looks pretty bad and seems quite inconvenient to me 
        foo = (ChildClass)foo.Deserialize("file.xml")
    }
}

我“需要”的东西是这样的:

class BaseClass
{
    public void Deserialize(string filePath)
    {
        using (StreamReader reader = new StreamReader(filePath))
        {
            XmlSerializer serializer = new XmlSerializer(this.GetType());
            this = (BaseClass)serializer.Deserialize(reader);
        }
    }
}

或者我可以使用构造函数吗?

最好的问候, 马丁

【问题讨论】:

  • 即使这段代码有效,也很难理解。你的扩展方法应该返回一个BaseClass,它不应该使用传入的参数。
  • DeserializeNOT 成员函数。它是一种扩展方法,不会返回它反序列化的对象。它使用bar,就好像它是一个临时变量
  • 你这里的设置是错误的。你的成员函数不应该接受一个参数,应该按照 this = new ChildClass(stuff); 的方式做一些事情。然后在课堂之外,如果需要,您可以将其转换为子类
  • 你正在寻找这个,它还没有实现。 github.com/dotnet/roslyn/issues/165
  • @PanagiotisKanavos 你是对的。最初我试图实现一个成员函数,但在我的尝试中我使用了扩展方法。我的错。

标签: c#


【解决方案1】:

这是不可能的。在您的情况下,“bar”是静态方法范围内的局部变量,最终您将其重新分配给不同的实例。您处理的不是同一个调用对象。

根据您尝试解决的解决方案,您可以将基类/子类分成两个单独的类,并在“子”中拥有一个“基”类型的成员。

【讨论】:

    【解决方案2】:

    我认为不可能从内部更改实例化对象。但是,您可以将初始化代码作为基类的一部分放入静态方法中,该方法显式返回可以分配给新变量的对象的新实例。这样,您只需通过该方法实例化您的类一次。

    基本上你会这样做:

    foo = (ChildClass)BaseClass.Deserialize("file.xml");
    

    这比从自身调用的方法重新分配 foo 更干净。然后您的 BaseClass 将具有:

    public static BaseClass Deserialize(String filePath) { ... }
    

    【讨论】:

    • 那我就不能从 BaseClass 派生我的 ChildClass 了吧?
    • 你是对的。我的逻辑倒退了。 BaseClass 实现需要是虚拟的,并且您的子类将覆盖它以返回正确的对象。因此,这种方法与使用一系列辅助方法来创建派生类没有什么不同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多