我有以下类层次结构。
public abstract class ResourceBase { }
public abstract class WebResourceBase : ResourceBase {
public ResourceBase LocalPath { get; set; }
public ResourceBase FtpPath { get; set; }
}
public class JavaScript : WebResourceBase { }
我想做的是有一个这样的声明。
new JavaScript() {
LocalPath = "/path/goes/here/1.js",
FtpPath = "ftp://path/goes/here/1.js"
}
这里明显的答案是使用隐式运算符,但问题是我想为那些与声明类型相同的属性分配派生类型,所以 LocalPath
和 FtpPath
将是 JavaScript
类型。
我希望我的解决方案比目前的解决方案更灵活。这段代码让我毛骨悚然。希望有一种使用反射的方法,我尝试使用 StackTrace
类查找信息,但没有成功。任何帮助,将不胜感激。谢谢。
public abstract class ResourceBase {
public static implicit operator ResourceBase(string path) {
if (path.EndsWith(".js"))
return new JavaScript(path);
// etc...
}
}
最佳答案
这假定 WebResourceBase
实际上是为了继承 ResourceBase
。
不幸的是,您无法使隐式运算符看起来更好——泛型在这里不起作用。
备选方案:约束 ResourceBase 的泛型
现在我已经重新阅读它并了解您的需求,一种选择是修改您的类以包含引用派生类的通用参数(有点像自引用):
public abstract class ResourceBase
{ }
public abstract class WebResourceBase<T> : ResourceBase
where T : WebResourceBase<T>
{
public T LocalPath { get; set; }
public T FtpPath { get; set; }
}
public class JavaScript : WebResourceBase<JavaScript>
{
}
然后你会看到在 JavaScript
中,属性 LocalPath
和 FtpPath
现在也是 JavaScript
类型.
现在您的作业将仅接受JavaScript
类型:
new JavaScript()
{
LocalPath = new JavaScript("/path/goes/here/1.js"),
FtpPath = new JavaScript("ftp://path/goes/here/1.js")
}
这种方法的好处是它将基本属性限制为当前类型或更派生的类型,而不是更少的派生类型。
替代方案:显式解析而不是
隐式
运算符
如果您需要将 LocalPath
和 FtpPath
变量保留为 ResourceBase
,否则不能在这里使用泛型,您的隐式运算符将开始变得困惑。最好提供一些明确的东西,比如静态方法:
new JavaScript()
{
LocalPath = JavaScript.Parse("/path/goes/here/1.js"),
FtpPath = JavaScript.Parse("ftp://path/goes/here/1.js")
}
class JavaScript
{
public static ResourceBase Parse(string s)
{
if (path.EndsWith(".js"))
return new JavaScript(path);
throw new Exception();
}
}
备选方案:类层次结构解析而不是
隐式
运算符
通过构造函数将使用字符串的概念烘焙到类型中,并将属性设为公共(public)只读:
public abstract class ResourceBase
{ }
public abstract class WebResourceBase
{
public ResourceBase LocalPath { get; private set; }
public ResourceBase FtpPath { get; private set; }
protected abstract ResourceBase ParseLocalPath(string s);
protected abstract ResourceBase ParseFtpPath(string s);
}
public class JavaScript : WebResourceBase<JavaScript>
{
protected override ResourceBase ParseLocalPath(string s)
{
// etc.
}
protected override ResourceBase ParseFtpPath(string s)
{
// etc.
}
}
老实说,只是为了从字符串中将两个属性设置为特定类型,其中的大部分内容似乎有点矫枉过正,您有很多选项 - 即使是隐式运算符也可以。
选择一个最容易理解的。运算符重载往往有些隐藏,除非您去挖掘它。
关于c# - 隐式运算符和类层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11452881/