【问题标题】:Explicit and implicit cast with generic type泛型类型的显式和隐式转换
【发布时间】:2017-09-10 11:25:39
【问题描述】:

我有这些课程:

public class FilterBackOfficeDiscountFilterType
{
    public FilterBackOfficeDiscountFilterType();
    public FilterBackOfficeDiscountFilterType(string filterValue = null, string filterType = null);

    [JsonProperty(PropertyName = "filterType")]
    public string FilterType { get; set; }
    [JsonProperty(PropertyName = "filterValue")]
    public string FilterValue { get; set; }
}

还有我的:

 public abstract class Filter<T>
    where T : struct
{
    public T Type { get; set; }
    public string Value { get; set; }
}

还有:

 public class DiscountFilter : Filter<DiscountFilterType>
{


}

我想以显式或隐式方式将DiscountFilter 转换为FilterBackOfficeDiscountFilterType

所以我添加了运算符方法:

 public class DiscountFilter : Filter<DiscountFilterType>
{
    public static implicit operator FilterBackOfficeDiscountFilterType(DiscountFilter filter)
        => new FilterBackOfficeDiscountFilterType(filterType: filter.Type.ToString(), filterValue: filter.Value);
}

但它没有编译,因为:

Cannot implicitly convert type 'Filter<DiscountFilterType>' to 'FilterBackOfficeDiscountFilterType'

我该怎么做?

DiscountFilterType 是一个枚举。

而 FilterCreator.Create 是:

public class DiscountFilterCreator : FilterCreator<DiscountFilterType>
{
    public override Filter<DiscountFilterType> Create(DiscountFilterType type, string value)
        => new DiscountFilter {Type = type, Value = string.IsNullOrWhiteSpace(value) ? null : value};
}

来源于:

public abstract class FilterCreator<T>
    where T : struct
{
    public abstract Filter<T> Create(T type, string value);
}

最后一个Filter 是:

public abstract class Filter<T>
    where T : struct
{
    public T Type { get; set; }
    public string Value { get; set; }
}

编辑 要重现问题,您必须这样做

DiscountFilter filter = new DiscountFilterCreator().Create(DiscountFilterType.normal, "wow"); 

编辑

DiscountFilter x = this.FilterCreator.Create(DiscountFilterType.BrandId, brandId);
        FilterBackOfficeDiscountFilterType y = x;

编辑 它有效:

    DiscountFilter x = (DiscountFilter)this.FilterCreator.Create(DiscountFilterType.BrandId, brandId);
        FilterBackOfficeDiscountFilterType y = x;

但我想这样做:

    FilterBackOfficeDiscountFilterType  x = this.FilterCreator.Create(DiscountFilterType.BrandId, brandId);

所以我也需要这种隐式转换:

   public class DiscountFilter : Filter<DiscountFilterType>
{
    public static implicit operator DiscountFilter(Filter<DiscountFilterType> filter)
        => new DiscountFilter {Value = filter.Value};
    public static implicit operator FilterBackOfficeDiscountFilterType(DiscountFilter filter)
        => new FilterBackOfficeDiscountFilterType(filterType: filter.Type.ToString(), filterValue: filter.Value);
}

但是不允许从派生类到基类的隐式转换!

DiscountFilter.implicit operator DiscountFilter(Filter<DiscountFilterType>): user-defined conversions to or from a base class are not allowed   

【问题讨论】:

  • 所有代码都在这里编译(考虑到一些拼写错误和重复的类型定义,但没关系)。
  • 你试过把这个操作符移到泛型类吗?
  • 不清楚你在问什么,因为你的代码确实编译得很好。
  • @Evk 是的,您可以重现该问题 DiscountFilter filter = new DiscountFilterCreator().Create(DiscountFilterType.normal, "wow")
  • @PatrickHofman 不是代码编译的问题 Nerf 没有提供如何重现问题

标签: c#


【解决方案1】:

(隐式)用户定义的从基类到派生类的转换是一个坏主意,因此语言不支持,正如这里已经解释的那样:User-defined conversion operator from base class

作为您的问题的解决方案,我建议调整您的基本类型如下:

public abstract class FilterCreator<TFilter, TFilterType>
    where TFilter : Filter<TFilterType>
    where TFilterType : struct
{
    public abstract TFilter Create(TFilterType type, string value);
}

public abstract class Filter<T>
    where T : struct
{
    public T Type { get; set; }
    public string Value { get; set; }
}

然后您可以将 DiscountFilterCreator 实现为

public class DiscountFilterCreator : FilterCreator<DiscountFilter, DiscountFilterType>
{
    public override DiscountFilter Create(DiscountFilterType type, string value)
        => new DiscountFilter { Type = type, Value = string.IsNullOrWhiteSpace(value) ? null : value };
}

使用它,您将不再需要强制转换,因为返回的类型是预期的类型。

不确定这是否正是您想要的。按照 C# 的标准,代码看起来很抽象,很可能有更好的设计来满足您的需求。

编辑:顺便说一句,这个实现使FilterCreator 非常接近无用。 Filter&lt;T&gt; 的用处似乎也很值得怀疑——你有没有声明过 Filter&lt;T&gt; 类型的变量或泛型约束?

【讨论】:

    【解决方案2】:

    为了重现您的问题,您尝试将基类泛型转换为派生类。

    类似的东西

    DiscountFilter filter = new DiscountFilterCreator().Create(DiscountFilterType.normal, "wow"); 
    

    要解决您的问题,您必须转换为派生类

     DiscountFilter filter =(DiscountFilter) new DiscountFilterCreator().Create(DiscountFilterType.normal, "wow"); 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 2011-09-12
      • 1970-01-01
      相关资源
      最近更新 更多