Explicit and Implicit Common Type Listing
I have these 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 mine:
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 pass DiscountFilter
in an FilterBackOfficeDiscountFilterType
explicit or implicit way.
So, I add an 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 doesn't compile because:
Cannot implicitly convert type 'Filter<DiscountFilterType>' to 'FilterBackOfficeDiscountFilterType'
How can i do this?
DiscountFilterType
is an enumeration.
And 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};
}
It comes from:
public abstract class FilterCreator<T>
where T : struct
{
public abstract Filter<T> Create(T type, string value);
}
And the last one Filter
:
public abstract class Filter<T>
where T : struct
{
public T Type { get; set; }
public string Value { get; set; }
}
Edit to reproduce the problem you should 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 like this:
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 implicit casting from the inherited class to the base is not allowed!
DiscountFilter.implicit operator DiscountFilter(Filter<DiscountFilterType>): user-defined conversions to or from a base class are not allowed
source to share
(Implicit) custom conversions from base class to derived class are a bad idea and, as such, are not supported by the language, as already explained here: Custom conversion operator from base class
As a solution to your problem, I would suggest setting up the base types like this:
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 simply implement DiscountFilterCreator like
public class DiscountFilterCreator : FilterCreator<DiscountFilter, DiscountFilterType>
{
public override DiscountFilter Create(DiscountFilterType type, string value)
=> new DiscountFilter { Type = type, Value = string.IsNullOrWhiteSpace(value) ? null : value };
}
By using this, you don't need to cast any more since the return type is expected.
Not sure if this is exactly what you want. The code seems very abstract by the C # standard, there is probably a better design for your needs.
EDIT: As a side note, this implementation makes it FilterCreator
very close to useless. The usefulness Filter<T>
also seems rather dubious - do you ever declare a variable or a generic type constraint Filter<T>
?
source to share
To reproduce your problem, you are trying to apply a base generic class to a derived class.
something like that
DiscountFilter filter = new DiscountFilterCreator().Create(DiscountFilterType.normal, "wow");
to solve your problem you should apply to the derived class
DiscountFilter filter =(DiscountFilter) new DiscountFilterCreator().Create(DiscountFilterType.normal, "wow");
source to share