C# 在 .NET 中初始化基类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/492872/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 05:32:46  来源:igfitidea点击:

Initialize base class in .NET

c#.netoop

提问by galets

How do I go about if I need to initialize an object's base with existing object? For example, in this scenario:

如果我需要使用现有对象初始化对象的基础,我该怎么办?例如,在这种情况下:

public class A
{
    public string field1;
    public string field2;
}

public class B : A
{
    public string field3;
    public void Assign(A source)
    {
        this.base = source; // <-- will not work, what can I do here?
    }
}

Assign() method can, obviously assign values to the base class field-by-field, but isn't there a better solution? Since class B inherits from A, there must be a way to just assign A to the B.base

Assign() 方法显然可以逐个字段地为基类赋值,但是没有更好的解决方案吗?由于类 B 继承自 A,因此必须有一种方法将 A 分配给 B.base

In C++ this would be a trivial thing to do, but I can't seem to grasp how to do this in .NET

在 C++ 中,这将是一件微不足道的事情,但我似乎无法掌握如何在 .NET 中做到这一点

采纳答案by Andrew Hare

Unfortunately baseis readonly.

不幸的base是是只读的。

[Edit]
Well perhaps not so unfortunate. The relationship between a base class and a child class is IS-Anot HAS-A. By allowing a child class to change the instance of the base class you are allowing the child class to change its own reference since it IS-Abase class. If you truly need this functionality then I would suggest you change your inheritance model to reflect what you truly want to do.

[编辑]
好吧,也许没那么不幸。基类和子类之间的关系IS-A不是HAS-A. 通过允许子类更改基类的实例,您允许子类更改它自己的引用,因为它是IS-A基类。如果您确实需要此功能,那么我建议您更改继承模型以反映您真正想做的事情。

Something like this:

像这样的东西:

public class A
{
    public string field1;
    public string field2;
}

public class B
{
    public string field3;
    public A a;

    public void Assign(A source)
    {
        this.a = source;
    }
}

seems more appropriate and has clearer meaning and functionality.

似乎更合适,具有更清晰的含义和功能。

回答by Nick Berardi

No, the syntax you are trying is not possible. In C# .NET you need to do:

不,您尝试的语法是不可能的。在 C# .NET 中,您需要执行以下操作:

public void Assign(A source) {
    field1 = source.field1;
    field2 = source.field2; 
}

回答by BFree

        public Assign(A a)
        {
            foreach (var prop in typeof(A).GetProperties())
            {
                this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(a, null),null);
            }
        }

Basically, it uses reflection to get all the properties of the base and assign the values of this, to all the values that exist in A.

基本上,它使用反射来获取基数的所有属性并将 this 的值分配给 A 中存在的所有值。

EDIT: To all you naysayers out there, I quickly tested this now with a base class that had 100 integer variables. I then had this assign method in a subclass. It took 46 milliseconds to run. I don't know about you, but I'm totally fine with that.

编辑:对于所有反对者,我现在使用具有 100 个整数变量的基类快速测试了它。然后我在子类中使用了这个分配方法。运行需要 46 毫秒。我不了解你,但我完全没问题。

回答by Sebastian Dietz

According to MSDN, "base" can only be used for the following operations:

根据 MSDN,“base”只能用于以下操作:

  • Call a method on the base class that has been overridden by another method.
  • Specify which base-class constructor should be called when creating instances of the derived class.
  • 调用已被另一个方法覆盖的基类上的方法。
  • 指定在创建派生类的实例时应调用哪个基类构造函数。

回答by tsilb

Why would you need to? By declaring a new B, the CLR automatically calls the constructors for both classes.

你为什么需要?通过声明一个新的 B,CLR 会自动调用两个类的构造函数。

B myB = new B();

B new has the fields of both classes. However, you should declare them with an initializer unless you like nulls:

B new 具有两个类的字段。但是,除非您喜欢空值,否则您应该使用初始化程序声明它们:

public string field1 = "";
public string field2 = string.Empty;

回答by Tamas Czinege

While there are many excellent answers here, I think the proper way to do this is by chaining the constructors:

虽然这里有很多很好的答案,但我认为正确的方法是链接构造函数:

public class A
{
    public string field1;
    public string field2;

    public A(string field1, string2 field2)
    {
         this.field1 = field1;
         this.field2 = field2;
    }
}

public class B : A
{
    public string field3;

    public B(string field1, string2 field2, string field3)
        : base(field1, field2)
    {
        this.field3 = field3;
    }
}

回答by Juliet

I hope I'm not the only one who thinks swapping out your base class is a bad design pattern. Another approach is to replace inheritance with composition:

我希望我不是唯一一个认为更换基类是一种糟糕的设计模式的人。另一种方法是用组合代替继承:

public class A
{
    public string Field1 { get; set; }
    public string Field2 { get; set; }
}

public class B
{
    public A A { get; set; }
    public string Field3 { get; set; }

    public B(A a) { this.A = a; }
}

Now its trivial to write something like this:

现在写这样的东西很简单:

B b = new B ( new A { Field1 = "hello", Field2 = "world" } );

b.A = new A { Field1 = "hola", Field2 = "luna" };

回答by Krzysztof Kozmic

Wrong question. You're obviously abusing inheritance here. Try to refactor it, so that you keep a reference to A as a member field. If you need polymorphism, consider having common base class or better yet - an interface.

错误的问题。你显然在这里滥用继承。尝试重构它,以便将 A 的引用保留为成员字段。如果您需要多态,请考虑使用公共基类或更好的 - 接口。

回答by AwesomeTown

Is the intent that these fields will be initialized once during object construction, or could "Assign" be called multiple times during an object's lifetime? If the latter, you can disregard the rest of this :)

这些字段的意图是在对象构造期间初始化一次,还是可以在对象的生命周期内多次调用“分配”?如果是后者,您可以忽略其余部分:)

Andrew's distinction between IS-A and HAS-A is an important one; if the relationship really is a HAS-A, his composition solution is the way to go.

Andrew 对 IS-A 和 HAS-A 的区分很重要;如果关系真的是 HAS-A,那么他的组合解决方案就是要走的路。

If an IS-A relationship makes more sense (and you are able to modify A), a copy constructor might be a good idea:

如果 IS-A 关系更有意义(并且您可以修改 A),那么复制构造函数可能是一个好主意:

public class A
{
    public string field1;
    public string field2;

    public A(A copyFrom)
    {
        this.field1 = copyFrom.field1;
        this.field2 = copyFrom.field2;
    }
}

public class B : A
{
    public string field3;

    public B(A source)
        : base(source)
    {
    }
}

You end up having to copy each of A's properties, but the responsibility for doing so resides in A where it belongs.

您最终不得不复制 A 的每个属性,但这样做的责任在于它所属的 A。

回答by aistrong

    [TestMethod]
    public void TestMethod()
    {
        A a = new A();
        a.field1 = "test";
        string xml = Serialize(a);
        xml = xml.Replace("A", "B");
        B b = Deserialize(xml);

        Assert.AreEqual("test", b.field1);
    }

    public string Serialize(A a)
    {
        System.IO.StreamReader streamReader = null;
        System.IO.MemoryStream memoryStream = null;
        try
        {
            memoryStream = new System.IO.MemoryStream();
            XmlSerializer serializer = new XmlSerializer(typeof(A));
            serializer.Serialize(memoryStream, a);
            memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
            streamReader = new System.IO.StreamReader(memoryStream);
            return streamReader.ReadToEnd();
        }
        finally
        {
            if ((streamReader != null))
            {
                streamReader.Dispose();
            }
            if ((memoryStream != null))
            {
                memoryStream.Dispose();
            }
        }
    }

    public static B Deserialize(string xml)
    {
        System.IO.StringReader stringReader = null;
        try
        {
            stringReader = new System.IO.StringReader(xml);
            XmlSerializer serializer = new XmlSerializer(typeof(B));
            return ((B)(serializer.Deserialize(System.Xml.XmlReader.Create(stringReader))));
        }
        finally
        {
            if ((stringReader != null))
            {
                stringReader.Dispose();
            }
        }
    }