C# 从基类获取子类属性

C# 从基类获取子类属性,c#,oop,reflection,C#,Oop,Reflection,假设我从矩形类创建了一个对象。有没有办法通过创建的对象写入矩形类对象的属性值,而不重写toString()方法 编辑: 实际上,我的目的是为所有子类创建一个泛型ToString()方法 我修改我的代码 public abstract class Shape { public String toString() { // ... return ""; } } public class Rectangle : Shape { pub

假设我从矩形类创建了一个对象。有没有办法通过创建的对象写入矩形类对象的属性值,而不重写toString()方法


编辑:

实际上,我的目的是为所有子类创建一个泛型ToString()方法

我修改我的代码

public abstract class Shape
{
    public String toString()
    {
        // ...
        return "";
    }
}

public class Rectangle : Shape
{
    public Double width { get; set; }
    public Double height { get; set; }
}
结果:

public abstract class Shape
{
    public virtual String ToString(Shape shape)
    {
        String result = String.Empty;

        foreach (var property in shape.GetType().GetProperties())
        {
            result += property.Name + " : " + property.GetValue(shape, null) + "\n";
        }

        return result;
    }
}



  public class Rectangle : Shape, IRectangle
    {
        public Double width { get; set; }
        public Double height { get; set; }

        public override String ToString()
        {
            return base.ToString(this);
        }
    }

但现在,我必须为所有子类重写ToString()方法。我无法找到此代码重复的解决方案

您不希望访问基类中的派生类,因为这样您必须为创建的每个派生更新基类

如果您完全确定不想只重写
ToString()
(您最好解释一下原因,因为这种方法在这种情况下最有意义),您可以这样做:

width : 0
height : 0

但实际上,您正在构建一个穷人的虚拟方法实现,您仍然必须为添加的每种类型维护这些方法。这与使用
重写ToString()
可以实现的功能完全相同,因此您必须有充分的理由不使用它

如果您只需要保留
toString
方法,您可以这样做

public abstract class Shape
{
    public String toString()
    {
        return ShapePrinter.GetString(this);
    }
}

public static class ShapePrinter
{
    public static string GetString(Shape shape)
    {
        if (shape is Rectangle)
        {
            return GetRectangleString(shape as Rectangle);
        }       
        if (shape is Circle)
        {
            return GetCircleString(shape as Circle);
        }

        throw new ArgumentException("shape");

    }

    private static string GetRectangleString(Rectangle rectangle)
    {
        return string.Format("Rectangle: {0} x {1}",
                              rectangle.Width, rectangle.Height);
    }

    private static string GetCircleString(Circle circle)
    {
        return string.Format("Circle: radius {0}", circle.Radius);
    }
}

“编写Recatangle类对象的属性…”我不确定我是否遵循。不,这是不可能的,因为基类对派生类一无所知。坦率地说,用其他方法来完成这项工作需要更多的工作。唯一的其他方法是在运行时在.ToString()中反映属性,并将所有代码保留在基类中但这似乎不是一个好主意。我现在看到你也给这个问题加上了标签
reflection
。这是您真正的问题吗?这与每次创建新的派生类型时必须更新基类有什么不同?您仍然必须更新它,但它位于单独的类中。正如我所说,您不想知道基类中实现基类的类型是什么,也不想让基类知道派生类,因为这样您就必须更新它。出于同样的原因,您不希望任何类知道类型的派生类型。所有这些都是由LSP解释的-ShapePrinter不能保证适用于从
Shape
派生的所有类型。不幸的是,这是一个Occam的剃刀般的情况:正确的方法是最简单的方法——让每个派生类型覆盖到字符串。“因为你将不得不更新它”——这不是你不想这样做的唯一原因。我完全同意你的推理(我希望我现在的答案能清楚地说明这一点),我只是给OP一些建议,如果他绝对确定他想以这种方式解决这个问题,并且忽略用于解决这个问题的机制,比如
覆盖
。如果任何派生类不在你的控制之下,这也不适用,你甚至可能不知道它们的存在。
public abstract class Shape
{
    public String toString()
    {
        return InternalToString();
    }

    protected abstract string InternalToString();
}

public class Rectangle : Shape
{
    public Double width { get; set; }
    public Double height { get; set; }

    protected override string InternalToString()
    {
        return width.ToString() + ", " + height.ToString();
    }
}