【问题标题】:class does not contain a definition for function类不包含函数的定义
【发布时间】:2018-08-26 14:51:05
【问题描述】:

我有一堆类都扩展了一个特定的基类,如下所示:

public class UIBaseProperties
{

}

public class EasyRawImage : UIBaseProperties
{
    public void SetImageDimensions(float? width = null, float? height = null)
    {
        if(width == null && height == null)
            RectOptions.sizeDelta = new Vector2(Img.width, Img.height);
        else if(width != null && height == null)
            RectOptions.sizeDelta = new Vector2((float)width, (float)width/Img.width*Img.height);
        else if(width == null && height != null)
            RectOptions.sizeDelta = new Vector2((float)height/Img.height*Img.width, (float)height);
        else if(width != null && height != null)
            RectOptions.sizeDelta = new Vector2((float)width, (float)height);
    }
}

现在我在另一个类中有一个 UIBaseProperties 列表,我向其中添加了所有从 UIBaseProperties 派生的不同实例,如下所示:

public class OpenRecordUI
{
    private List<UIBaseProperties> UIElements;

    public OpenRecordUI()
    {
        UIElements = new List<UIBaseProperties>();
        UIElements.Add(new EasyRawImage(Resources.Load("Images/" + Data.local_photo_name), new Vector2(50, 50), v.GetActualPixelSizes().size.x, v.GetActualPixelSizes().size.y));
        var test = UIElements[0].SetImageDimensions(); // error
    }
}

现在当我尝试调用 SetImageDimensions() 函数时出现错误。我得到的错误如下:

“UIBaseProperties”不包含“SetImageDimensions”的定义,也没有扩展方法“SetImageDimensions”

我知道为什么会出现错误,但我不知道如何以其他方式执行此操作。
这甚至可能吗,否则应该怎么做?

如果有什么不清楚的,请告诉我,以便我澄清!

【问题讨论】:

  • SetImageDimensions 只属于EasyRawImage
  • @Nkosi 是的,我知道,但我的问题是:“有没有办法从基类访问“SetImageDimensions?”
  • 在这里你想做什么并不完全清楚——如果你想要一个可以调用SetImageDimensions的事情列表,那么你需要一个List&lt;EasyRawImage&gt;。作为一般规则,如果您有多个类需要以不同方式进行交互,那么您不应该尝试将它们视为同一事物。
  • @FutureCake 这似乎是XY problem。您要解决的实际问题是什么?
  • @FutureCake 从您发布的内容来看,尚不清楚为什么需要基类,甚至是列表。很明显,您犯了一些设计错误,但如果不了解更多信息,就不可能提出改进建议,而不仅仅是糟糕的解决方法。

标签: c# function class generics inheritance


【解决方案1】:

您可以将UIBaseProperties 声明为abstract 类,将SetImageDimensions 声明为abstract 方法。然后在来自UIBaseProperties 的每个派生类中,您应该提供此方法的实现。

public abstract class UIBaseProperties
{
    public abstract SetImageDimensions(float? width = null, float? height = null);
}

然后通过覆盖SetImageDimensions,错误将不再存在。

public class EasyRawImage : UIBaseProperties
{
    public override void SetImageDimensions(float? width = null, float? height = null)
    {
        if(width == null && height == null)
            RectOptions.sizeDelta = new Vector2(Img.width, Img.height);
        else if(width != null && height == null)
            RectOptions.sizeDelta = new Vector2((float)width, (float)width/Img.width*Img.height);
        else if(width == null && height != null)
            RectOptions.sizeDelta = new Vector2((float)height/Img.height*Img.width, (float)height);
        else if(width != null && height != null)
            RectOptions.sizeDelta = new Vector2((float)width, (float)height);
    }
}

另一种方法是避免继承(定义一个基类,然后从它派生等)。通过声明一个接口,然后你提到的每个类都实现这个接口,你可以得到相同的结果:

// The name of the interface is not very good, you should probably 
// think for another name.
public interface IUIBaseProperties
{
    void SetImageDimensions(float? width = null, float? height = null)
}

然后重新声明你的类如下:

public class EasyRawImage : IUIBaseProperties
{
    public void SetImageDimensions(float? width = null, float? height = null)
    {
        if(width == null && height == null)
            RectOptions.sizeDelta = new Vector2(Img.width, Img.height);
        else if(width != null && height == null)
            RectOptions.sizeDelta = new Vector2((float)width, (float)width/Img.width*Img.height);
        else if(width == null && height != null)
            RectOptions.sizeDelta = new Vector2((float)height/Img.height*Img.width, (float)height);
        else if(width != null && height != null)
            RectOptions.sizeDelta = new Vector2((float)width, (float)height);
    }
}

并按如下方式使用:

public class OpenRecordUI
{
    private List<IUIBaseProperties> UIElements;

    public OpenRecordUI()
    {
        UIElements = new List<IUIBaseProperties>();
        UIElements.Add(new EasyRawImage(Resources.Load("Images/" + Data.local_photo_name), new Vector2(50, 50), v.GetActualPixelSizes().size.x, v.GetActualPixelSizes().size.y));
        var test = UIElements[0].SetImageDimensions();
    }
}

【讨论】:

  • @FutureCake 不是问题:)。我刚刚编辑了我的答案。
  • @FutureCake 谢谢,希望回答对您有所帮助!
  • 是的,绝对是!
  • @Nkosi 好评!我会再次编辑答案。谢谢
  • @Nkosi 或者更好的是让基本实现成为无操作,并在需要的地方覆盖它......不过,这对我来说仍然感觉有点不对劲,因为SetImageProperties 可能毫无意义对于大多数类型的UIBaseProperties - 我通常更愿意在EasyRawImages 被混合到通用集合之前明确地应用它......但很难在提供的上下文中做得更好。
【解决方案2】:

错误告诉你到底哪里出了问题。类UIBaseProperties 没有方法SetImageDimensions

当您创建一个包含特定类型对象的列表时,它们都被视为完全属于该类型。当然,您可以将继承自定义中的类的实例存储在其中,但它们仍被视为父类的实例。

在您的情况下,列表中的所有内容都被视为UIBaseProperties 的实例,即使它们是子类EasyRawImage 的实例。由于父类没有方法SetImageDimensions,因此您无法访问它,即使您的对象确实包含它。

要解决这个问题,您需要在访问每个对象时将其转换回子类型,如下所示:

((EasyRawImage)UIElements[0]).SetImageDimensions();

然而,这被认为是不好的做法。最好不要首先将列表定义为包含UIBaseProperties 对象。相反,请使用抽象类或接口模式之类的东西。

【讨论】:

    【解决方案3】:

    问题的原因是UIElements[0] 的类型是UIBaseProperties

    如果UIElements 集合只能包含EasyRawImage 类型的东西,那么它应该被输入为List&lt;EasyRawImage&gt;,那么你就可以用你已经拥有的那一行来调用那个方法了。

    但是,如果您打算将该基类的其他实现放入集合中,那么您需要保持原样;但是在使用之前,您需要确保该项目属于该类型。您可以使用((EasyRawImage)UIElements[0])(如果不是那种类型,则会失败)而不是强制转换它:

    var test = UIElements[0] asEasyRawImage;
    if (test != null)
    {
        test.SetImageDimensions();
    }
    

    【讨论】:

      猜你喜欢
      • 2017-02-02
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2012-09-10
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      相关资源
      最近更新 更多