这假设这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")
}
这种方法的好处是它将基础属性限制为当前类型或更多派生,而不是更少派生。
替代方案:显式解析而不是implicit
运算符
如果您需要将LocalPath
andFtpPath
变量保留为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();
}
}
替代方案:类层次结构解析而不是implicit
运算符
通过构造函数将使用字符串的概念烘焙到类型中,并使属性 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.
}
}
老实说,只是为了从字符串中将两个属性设置为特定类型,这似乎有点矫枉过正,你有很多选择——即使是隐式运算符也可以工作。
选择一个最容易理解的。除非你去挖掘它,否则运算符重载往往会被隐藏起来。