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