Explicit and implicit cast with generic type

Nerf

I have those classes:

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

And my:

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

And:

 public class DiscountFilter : Filter<DiscountFilterType>
{


}

I want to cast DiscountFilter to FilterBackOfficeDiscountFilterType in explicit or implicit way.

So I add operator method:

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

But it do not compile because:

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

How I can do it?

DiscountFilterType is a enum.

And FilterCreator.Create is:

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

It derives from:

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

And last Filter is:

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

Edit to reproduce the issue you have to do this

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

EDIT

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

Edit It works:

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

but I want to do it this way:

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

So I need this implicit conversion too:

   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);
}

But the implicit casting from derivered class to base is not allowed!

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

(Implicit) user-defined conversions from base class to derived class are a bad idea and as such not supported by the language as already explained here: User-defined conversion operator from base class

As a solution to your problem, I'd propose to adjust your base types as follows:

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

Then you can just implement the DiscountFilterCreator as

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

Using this, you will no longer need casts since the returned type is the expected type.

Not sure this is exactly what you want. The code seems very abstract by C#'s standards, it's probable that there is a better design for your needs.

EDIT: Just as a side note, this implementation renders the FilterCreator very close to useless. The usefulness of Filter<T> seems rather questionable as well - do you ever declare a variable or generic contraint of type Filter<T>?

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Generic method performs implicit cast while non-generic method needs explicit cast

Cast unknown object to generic interface of interface (from initially explicit generic type of generic collection type of type)

Generic type constraint does not enable assignment without explicit cast

Explicit type annotation for generic constructor of a generic type

Usage of generic type for explicit conversion

Invalid cast with generic type

Generic Type cast

Type cast to Generic

Swift generic type cast

cast of generic type fails

Unsound implicit cast warning not shown for generic parameter

Explicit vs implicit type definition in TensorFlow

explicit/implicit type conversion c++

crosswise implicit / explicit type conversation of records in pascal

c++ - how to properly overload operator to do implicit type cast from __generic_buffer<void*> to __generic_buffer<const void*>?

Typescript Generic with implicit attribute type

Implicit type argument in generic class

Implicit casting IEnumerable to generic type

Why does this explicit cast not work when there is an implicit conversion defined?

Convert float to int implicit vs explicit (cast) discrepancy

Generic Programming in Go, Implicit generic type

Explicit cast to defined type throws `InvalidCastException`

Implicit conversion with a generic type failing for an interface type

How to cast generic type to Object?

Cast to compiletime unknown generic type

Java generic cast by parameter type

Cast generic class to different type

Swift Cast to Generic Type with Constraint

Cast to a type from a generic class