初学者:用 C# 扩展一个类,我做错了吗?
再说一遍免责声明总体上仍在学习 C# 和 OOP,所以我希望你能对我有耐心 :)
我目前正在使用一个 CMS,它有一个名为 FileVersion
的类,它基本上包含与文件相关的属性列表,例如文件名、文件类型、字节大小、id、上传日期、最新版本等。
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 对我来说相对较新,所以我可能是错的。
预先感谢您的帮助。这个社区太有价值了!我只是希望一旦我更加熟练,我可以回馈一些:)。
Again disclaimer disclaimer still learning C# and OOP generally so I hope you'll be patient with me :)
I am currently working with a CMS that has a class called FileVersion
which basically contains a list of properties pertaining to a file such as filename, filetype, size in bytes, id, date uploaded, is-latest-version, etc.
A list of FileVersion
s is contained within a File
which has it's own unique ID. When you want to download a particular file from the CMS, the URL is built using something like the following:
string URL = "/files/"+file.id.toString()+"/"+file.fileVersion.Last().filename;
Now for a particular control I'm working on (dealing specifically with files that are documents), it makes sense to be able to store the URL along with all the other FileVersion
information for later use. So what I've decided to do is create my own class called DocumentVersion
which extends FileVersion
. This is what it looks like:
public partial class DocumentVersion : FileVersion
{
public DocumentVersion() : base() { }
public string link;
}
Now I should note, that it appears that I don't need to implement an interface here - but don't take that as gospel, that's why I'm here.
However when I try to cast my FileVersion
as a DocumentVersion
like so:
DocumentVersion dv = ((DocumentVersion)fileversion);
I get the following exception:
Unable to cast object of type
'Foo.CMS.FileVersion' to type
'CoA.DocumentVersion'.
My inkling is that it's because I'm trying to extend a class in a different namespace from where the original resides, but like I said, OOP is relatively new to me so I could be wrong.
Thanks in advance for your help. This community has been so valuable! I just hope once I'm more skilled up I can give some back :).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
你想沮丧吗?即采用现有的
FileVersion
并将其声明为DocumentVersion
?如果是这样,您就不能这样做,因为您所拥有的只不过是一个
FileVersion
。相反,您需要创建一个新
DocumentVersion
对象。您的DocumentVersion
构造函数将获取FileVersion
所需的参数,然后通过base()
调用FileVersion
构造函数。请注意,如果您有一个现有的
FileVersion
对象,您可能需要一个对象来包装它,而不是从它派生一个对象。例如,您的DocumentVersion
不会从FileVersion
派生,但包含对FileVersion
的私有引用,以及所需的其他数据。在这种情况下,这可能更合适。例如(在面向对象的术语中,这是组合)
请参阅此处了解有关构图的更多信息。
Are you trying to downcast ? i.e. take an existing
FileVersion
and declare it to be aDocumentVersion
?If so, you can't do that, since what you have is nothing more than a
FileVersion
.Instead you need to create a new
DocumentVersion
object. YourDocumentVersion
constructor will take the arguments required for aFileVersion
and then call theFileVersion
constructor viabase()
.Note that if you have an existing
FileVersion
object, you may want an object to wrap this, rather than have an object deriving from it. e.g. yourDocumentVersion
wouldn't derive fromFileVersion
, but contain a private reference to aFileVersion
, plus additional data as required. That may be more appropriate in this scenario.e.g. (in OO terms this is composition)
See here for more info on composition.
您无法将
FileVersion
转换为DocumentVersion
,因为您的 fileversion 变量包含 FileVersion,而不是 DocumentVersion。 继承意味着以下内容:如果对象是作为 FileVersion 创建的,那么它只是一个 FileVersion。时期。如果它是作为 DocumentVersion 创建的,那么您可以在任何需要使用 FileVersion 的地方使用它(请参阅上面的规则 #1),并且您可以使用它的 DocumentVersion 功能。
因此,当创建 FileVersion 对象时,您需要创建一个 DocumentVersion (如果您可以控制这部分代码),那么转换就会起作用。这些 DocumentVersions 可以存储在与 FileVersions 相同的列表中,因为每个 DocumentVersion 也是一个 FileVersion。
编辑:由于上述两条规则对于理解 OO 原则非常重要,让我用一个例子来说明它们:DocumentVersion = dogs 和 FileVersion = Animal。那么上述规则将是:(1)每只狗都是动物,但(2)并非每只动物都是狗。因此,您可以创建一个动物列表,在其中存储各种动物(狗,猫,只是“动物”的东西,...),但是您不能将动物类型的变量强制转换为狗,除非什么在那里已被创建为狗(或贵宾犬(贵宾犬类:狗),根据规则(1),它是狗)。
用面向对象的术语来说:如果将狗存储在动物类型的变量中,则该对象的静态类型是“animal”,动态类型是“dog” 。如果元素的动态类型是 T 或其子类型,则只能将其强制转换为某种类型 T。
You cannot cast your
FileVersion
toDocumentVersion
because your fileversion variable contains a FileVersion, not a DocumentVersion. Inheritance means the following:If the object was created as a FileVersion, it's just a FileVersion. Period. If it was created as a DocumentVersion, you can use it everywhere where you would use a FileVersion (see rule #1 above), and you can use the DocumentVersion features of it.
So, when creating the FileVersion object, you need to create a DocumentVersion instead (if you have control over that part of the code), then the cast will work. Those DocumentVersions could be stored in the same list as the FileVersions, since every DocumentVersion is also a FileVersion.
EDIT: Since the above two rules are so vital to understanding the OO principle, let me illustrate them with an example: DocumentVersion = dog and FileVersion = animal. Then the above rules would be: (1) Every dog is an animal, but (2) not every animal is a dog. So, you can create a list of animals, store all kinds of animals in there (dogs, cats, things that are just "animal", ...), but you cannot cast a variable of type animal to a dog, unless what is in there has been created as a dog (or as a poodle (class poodle : dog), which is a dog by rule (1)).
In OO terms: If you store a dog in a variable of type animal, then the static type of the object is "animal", and the dynamic type is "dog". You can only cast an element to some type T if its dynamic type is T or a subtype thereof.
您无法让父亲 (
FileVersion
) 表现得像儿子 (DocumentVersion
)。只有反之亦然=>你可以让儿子当父亲。
(FileVersion)documentVersion //有效
(DocumentVersion)fileVersion //无效(因为 fileVersion 无法了解派生类型拥有的内容)
这是 OOP 基础知识。
You can't make father (
FileVersion
) to act like son (DocumentVersion
).Only vica versa => you can make son as father.
(FileVersion)documentVersion //valid
(DocumentVersion)fileVersion //invalid (because fileVersion can't know about stuff that derived type has)
That's OOP basics.
(正如大多数答案所说,您无法进行备份 -
FileVersion
不知道DocumentVersion
是什么)。一种获取方法围绕它的方法是复制
DocumentVersion
构造函数中的字段,或者在
DocumentVersion
上创建一个静态方法,从FileVersion 返回一个
你提供它,例如:DocumentVersion
提到的另一种技术是组合。您将
FileVersion
作为属性存储在DocumentVersion
中(As most answers have said, you can't cast back up -
FileVersion
has no idea what aDocumentVersion
is).One way to get around it is to copy the fields in the constructor of
DocumentVersion
Or create a static method on
DocumentVersion
that returns aDocumentVersion
from theFileVersion
you provide it, e.g:Another technique mentioned, is composition. You store the
FileVersion
as a property inDocumentVersion
由于您无法将
FileVersion
转换为DocumentVersion
并且您需要做的就是添加一个方法来获取 URL,因此您可以创建一个 采用FileVersion
的扩展方法:注意:这仅在您使用 C# 3.0 时有效。
Since you cannot convert a
FileVersion
to aDocumentVersion
and all you need to do is add a method to get the URL, you could create an extension method that takes aFileVersion
:Note : this only works if you are using C# 3.0.