初学者:用C#扩展一个类,我做错了吗?

时间:2009-11-10 10:42:13

标签: c# class casting extend

再次免责声明免责声明仍在学习C#和OOP,所以我希望你能耐心等待我:)

我目前正在使用一个名为FileVersion的CMS的CMS,它基本上包含与文件相关的属性列表,例如文件名,文件类型,字节大小,id,上传日期,is-latest-版本等

FileVersion的列表包含在File中,其中包含自己的唯一ID。如果要从CMS下载特定文件,则使用以下内容构建URL:

string URL = "/files/"+file.id.toString()+"/"+file.fileVersion.Last().filename;

现在对于我正在处理的特定控件(专门处理文档文件),能够将URL与所有其他FileVersion信息一起存储以供以后使用是有意义的。所以我决定创建自己的名为DocumentVersion的类,它扩展了FileVersion。这就是它的样子:

public partial class DocumentVersion : FileVersion
{
    public DocumentVersion() : base() { }
    public string link;
}

现在我应该注意,似乎我不需要在这里实现一个接口 - 但是不要把它作为福音,这就是我在这里的原因。

但是,当我尝试将FileVersion投射为DocumentVersion时,就像这样:

DocumentVersion dv = ((DocumentVersion)fileversion);

我得到以下异常:

  

无法投射类型的对象   输入'Foo.CMS.FileVersion'   'CoA.DocumentVersion'。

我的意思是,这是因为我试图将一个类扩展到原来所在的不同名称空间中,但就像我说的那样,OOP对我来说相对较新,所以我可能错了。

提前感谢您的帮助。这个社区非常有价值!我只希望一旦我更熟练,我就可以回馈一下:)。

6 个答案:

答案 0 :(得分:5)

你正试图垂头丧气吗?即,取一个现有的FileVersion并声明它是DocumentVersion

如果是这样,你不能这样做,因为你所拥有的只不过是FileVersion

相反,您需要创建一个 DocumentVersion对象。您的DocumentVersion构造函数将获取FileVersion所需的参数,然后通过FileVersion调用base()构造函数。

请注意,如果您有一个现有的FileVersion对象,则可能需要一个对象 wrap ,而不是从中获取对象。例如您的DocumentVersion不会来自FileVersion,但包含对FileVersion的私人引用,以及所需的其他数据。在这种情况下,这可能更合适。

e.g。 (在OO术语中,这是组合

public class DocumentVersion {
   private FileVersion fv;
   private String url;
   public DocumentVersion(FileVersion fv, String url) {
      this.fv = fv;
      this.url = url;
   }
}

有关构图的更多信息,请参阅here

答案 1 :(得分:4)

您无法将FileVersion转换为DocumentVersion,因为您的fileversion变量包含FileVersion,而不是DocumentVersion。 继承表示以下内容:

  • 每个DocumentVersion都是FileVersion,但
  • 每个FileVersion都是DocumentVersion!

如果对象是作为FileVersion创建的,那它只是一个FileVersion。期。如果它被作为DocumentVersion创建的,你可以用它无处不在那里你可以使用一个文件版本(参见上面的规则#1)的的你可以用它的DocumentVersion功能。

因此,当创建 FileVersion对象时,您需要创建一个DocumentVersion(如果您可以控制该部分代码),那么转换将起作用。那些DocumentVersions可以存储在与FileVersions相同的列表中,因为每个DocumentVersion也是一个FileVersion。


编辑:由于上述两条规则对于理解OO原则至关重要,让我用一个例子来说明它们:DocumentVersion = dog和FileVersion = animal。然后上述规则是:(1)每只狗都是动物,但(2)并非每只动物都是狗。所以,你可以创建一个动物列表,在那里存储各种动物(狗,猫,只是“动物”的东西,...),但你不能把一个变种类型的动物投入到狗,除非什么在那里被创造为一只狗(或一只狮子狗(班贵宾犬:狗),其中是规则(1)的狗。

在OO术语中:如果将狗存储在动物类型的变量中,则对象的静态类型为“animal”,动态类型为“狗”。如果元素的动态类型为T或其子类型,则只能将元素强制转换为某种类型。

答案 2 :(得分:1)

你不能让父亲(FileVersion)像儿子一样行事(DocumentVersion) 只有vica versa =>你可以让儿子成为父亲。

(FileVersion)documentVersion //有效
(DocumentVersion)fileVersion //无效(因为fileVersion无法知道派生类型有的东西)

那是OOP的基础。

答案 3 :(得分:1)

DocumentVersion dv = null;

if (fileversion is DocumentVersion)
{
    dv = fileversion as DocumentVersion;
}

答案 4 :(得分:1)

(正如大多数答案所说,你无法重新投票 - FileVersion不知道DocumentVersion是什么。

解决它的一种方法是复制DocumentVersion

的构造函数中的字段
public partial class DocumentVersion : FileVersion
{
    public DocumentVersion() : base() { }

    public DocumentVersion(FileVersion version) : this()
    {
        this.id = version.id;
        // etc.
    }

    public string Link { get;set; }
}

或者在DocumentVersion上创建一个静态方法,从您提供的DocumentVersion返回FileVersion,例如:

public static void New(FileVersion version)
{
    this.id = version.id;
    // etc.
}

提到的另一种技术是组合物。您将FileVersion存储为DocumentVersion

中的媒体资源
public class DocumentVersion
{
    public FileVersion FileVersion { get;set; }
    public string Link { get;set; }
}

答案 5 :(得分:0)

由于您无法将FileVersion转换为DocumentVersion,而您需要做的就是添加一个获取网址的方法,您可以创建一个extension method来获取{{1} }}:

FileVersion

注意:这仅在您使用C#3.0时有效。