c# - 隐式运算符和类层次结构

标签 c#

我有以下类层次结构。

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"
}

这里明显的答案是使用隐式运算符,但问题是我想为那些与声明类型相同的属性分配派生类型,所以 LocalPathFtpPath 将是 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 中,属性 LocalPathFtpPath 现在也是 JavaScript 类型.

现在您的作业将接受JavaScript 类型:

new JavaScript() 
{
    LocalPath = new JavaScript("/path/goes/here/1.js"),
    FtpPath = new JavaScript("ftp://path/goes/here/1.js")
}

这种方法的好处是它将基本属性限制为当前类型或更派生的类型,而不是更少的派生类型。


替代方案:显式解析而不是隐式运算符

如果您需要将 LocalPathFtpPath 变量保留为 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/

相关文章:

c# - DateTime.Now 没有小数秒

c# - C# 中的快速字节数组屏蔽

c# - 具有基本身份验证的 HTTP URL 的正则表达式

c# - 这个内部类静态作用域魔术是如何工作的?

c# - 确保List <T>类型中的所有元素均为T

c# - 用枚举的名称填充下拉列表

c# - 我如何处理在 .NET 中使用多种货币的国家?

c# - 通过 Excel-DNA 将 Excel.Range 从 VBA 传递到 C#

c# - Xamarin Android : How do i pass variables to a buttons event method in ExpandableListView?

c# - 如何找到进程的开始和结束内存?