我有几个类,我在访问其他类方法中的子类中定义的属性时遇到了问题。
我有一个名为Section
的基类和一些子类,例如SectionPlane : Section
。在每个子类中,定义了一组不同的字段和属性(在SectionPlane
中,私有字段_t
和公共属性t
可以找到,而在SectionExtruded : Section
我有私有字段_A
和公共属性'A')。
课程部分
// General section object
public abstract class Section
{
public Section()
{}
}
班级平面部分
// Section object representing a plane with thickness t
public class SectionPlane : Section
{
private double _t;
public SectionPlane(double t)
{
this.t = t;
}
public double t
{
get
{
return _t;
}
set
{
_t = value;
}
}
}
课程挤压部分
// Section object of some geometry with cross section area A extruded along the element it is assigned to.
public class SectionExtruded : Section
{
private double _A;
public SectionExtruded(double A)
{
this.A = A;
}
public double A
{
get
{
return _A;
}
set
{
_A = value;
}
}
}
当我从类Element
的任何子类尝试访问属性时,会出现问题,因为没有在基类Section
中设置,例如在元素Solid2D : Element
中:
类元素
public abstract class Element
{
private Section _section;
public Element(Section section)
{
this.section = section;
}
public Section section
{
get
{
return _section;
}
set
{
_section = value;
}
}
}
}
类固体2D元素
// Solid2D elements can only have sections of type SectionPlane
public class Solid2D : Element
{
public Solid2D(SectionPlane section)
: base(section)
{
}
public void Calc()
{
double t = section.t; // This results in error 'Section' does not contain a definition for 't' and no extension method 't' accepting a first argument of type 'Section' could be found (are you missing a using directive or an assembly reference?)
}
}
条形元素
// Bar elements can only have sections of type SectionExtruded
public class Solid2D : Element
{
public Solid2D(SectionExtruded section)
: base(section)
{
}
public void Calc()
{
double A = section.A; // This results in error 'Section' does not contain a definition for 'A' and no extension method 'A' accepting a first argument of type 'Section' could be found (are you missing a using directive or an assembly reference?)
}
}
有没有办法访问我的属性t
而无需将其包含在基类Section
中?这将非常有用,因为并非我将使用的所有部分都具有相同的属性。
答案 0 :(得分:7)
因为你知道它只能是SectionPlane
你可以施展它
double t = ((SectionPlane)section).t;
如果您不确定自己是否有正确类型的部分,可以使用as
关键字
double t = 0;
var sectionPane = section as SectionPlane;
if (sectionPane != null) {
t = sectionPane.t;
}
如果该部分具有其他类型,则 as
不会抛出异常,而是返回null
。
或者你可以简单地测试
double t = 0;
if(section is SectionPlane) {
t = ((SectionPlane)section).t;
}
但这不如使用as
那么优雅,因为你必须测试类型然后再投射它;但是在内部再次进行测试。
使用C#7.0中引入的新模式匹配,您可以编写:
double t = 0;
if(section is SectionPlane sp) {
t = sp.t;
}
但是如果你必须进行这样的测试,问题是,你的方法是否适合面向对象的意义。如果将Calc
- 方法移动到抽象类Section
并让每个类执行自己的计算,则不需要进行任何类型测试或转换。
在Section
:
public abstract void Calc();
在SectionPlane
public override void Calc()
{
var x = t;
}
...
section.Calc(); // No casting or type test required.
答案 1 :(得分:1)
我会说,将属性“t”放在Section基类中,如果属于那里的话。
答案 2 :(得分:0)
以下是一些选项:
Element.section
更改为SectionPlane
。section
投放到SectionPlane
中的Calc()
。t
添加到Section
。IHasT
属性的界面(例如t
),让SectionPlane
实现此功能,并将Element.section
更改为IHasT
。public abstract class Element
更改为public abstract class Element<T> where T : Section
,将section
更改为T
,然后Solid2D : Element<SectionPlane>
答案 3 :(得分:0)
如果您知道元素继承者将使用的部分类型,我将使元素基类成为通用:
public abstract class Element<SectionType>
where SectionType:Section
{
//....
}
您可以使用基类包含默认元素类型:
public abstract class Element:Element<Section>
{
//....
}
已知元素可以继承强类型:
public class Solid2D : Element<SectionPlane>