C#访问子类属性

时间:2012-06-17 18:07:42

标签: c# .net properties polymorphism

我有几个类,我在访问其他类方法中的子类中定义的属性时遇到了问题。

我有一个名为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中?这将非常有用,因为并非我将使用的所有部分都具有相同的属性。

4 个答案:

答案 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)

以下是一些选项:

  1. Element.section更改为SectionPlane
  2. section投放到SectionPlane中的Calc()
  3. t添加到Section
  4. 创建一个具有IHasT属性的界面(例如t),让SectionPlane实现此功能,并将Element.section更改为IHasT
  5. (如果适用)将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>