Reputation: 1100
I have different types of item. Each of them has a enum where ID's are keept. I want my base class to have a method to check if the item's ID is on a given list. Something like:
abstract class Thing
{
public string Name;
public int Amount;
//others
abstract bool IsInList(list<xxxxx> list);
abstract xxxxxxx ID;
}
class Fruit : Thing
{
public IDs = {F_NotSet, F_Banana, F_Apple, ...}
public IDs ID = IDs.F_NotSet;
public bool IsInList(List<T> list) //this wont compile
{
if(typeof(T) == typeof(IDs))
return list.Contains(IDs);
else
return false;
}
}
The thing is that I also have a (blazor) UI component that visualizes things so I want to be able to do my
<div>@Thing.Name [@Thing.Amount]</div>
<code>
[Parameter] public Thing Thing {get;set;}
</code>
And use it on my page for all kind of things, like :
<div>
@foreach(var thing in Things) //things being List<Thing>
{
<ThingViewer ItemToShow=thing/>
}
</div>
That's why I don't want to go the Thin<T>
path because then my UI component to visualize Things and my page gets messy.
On the other side, I would like to use this "IsInList" method from the page to do things like
<div>
@foreach(var thing in MyThings) //MyThings being List<Thing>
{
@if(thing.IsInList(ThingsInOffer))
{
<div class="offer">
<ThingsVisualizer ItemToShow=thing/>
</div>
}
}
</div>
Upvotes: 1
Views: 91
Reputation: 16104
Here is the complete working example from fiddle, that helped solve the issue:
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections.Generic;
public class Program
{
// Just for showcasing:
public static void Main()
{
var apple = new Fruit(Fruits.Apple);
var banana = new Fruit(Fruits.Banana);
var orange = new Fruit(Fruits.Orange);
var strawberry = new Nut(Nuts.Strawberry);
var assortedFruits = new []{ Fruits.Apple, Fruits.Orange };
Console.WriteLine("I ({0}) am {1}an assorted fruit!", apple.Id, apple.IsInList(assortedFruits)?"":"not ");
Console.WriteLine("I ({0}) am {1}an assorted fruit!", banana.Id, banana.IsInList(assortedFruits)?"":"not ");
Console.WriteLine("I ({0}) am {1}an assorted fruit!", strawberry.Id, strawberry.IsInList(assortedFruits)?"":"not ");
PrintDetails(apple);
PrintDetails(banana);
PrintDetails(orange);
PrintDetails(strawberry);
foreach( var thing in new IThing[]{apple, strawberry} )
{
Console.WriteLine($"{thing.Name}s have {thing.SomeProperty}");
}
}
public static void PrintDetails(IThing thing)
{
// Going by an interface: We do not really care, what kind of
// "thing" it is in particular.
thing.Print();
}
}
// Two "Kinds" of Things: Fruits and Nuts
public enum Fruits
{
Apple,
Banana,
Orange
}
public enum Nuts
{
Strawberry
}
// Things all kinds of "Things" need to be able to do:
public interface IThing
{
void Print();
string Name {get;}
string SomeProperty {get;}
}
// Common generic implementations:
public abstract class Thing<TIdentifyingThing> : IThing
{
protected TIdentifyingThing _me;
protected Thing(TIdentifyingThing id)
{
_me = id;
}
public TIdentifyingThing Id => _me;
public string Name => _me.ToString();
public abstract string SomeProperty {get;}
// I think the "thing" here was that you can have generic methods
// with Types that do not need to be the same as the generic class's
// type. Here `T` versus `TIdentifyingThing`.
public bool IsInList<T> (IEnumerable<T> list)
{
if( typeof(T) != typeof(TIdentifyingThing) ) return false;
if( list is not null && list.Any() )
{
return list.Cast<TIdentifyingThing>().Contains(_me);
}
return false;
}
public abstract void Print();
}
// The specific Things:
public class Fruit : Thing<Fruits>
{
public Fruit( Fruits identity ): base(identity) {}
public override string SomeProperty => "just some property.";
public override void Print()
{
Console.WriteLine($"My fruity details are: I am a{(Id.ToString().StartsWithVocal() ? "n" : "" )} {Id}.");
}
}
public class Nut : Thing<Nuts>
{
public Nut( Nuts identity ): base(identity) {}
public override string SomeProperty => "not always the appearance you expect.";
public override void Print()
{
Console.WriteLine($"My nutty details are: I am a{(Id.ToString().StartsWithVocal() ? "n" : "" )} {Id}.");
}
}
// Just so the code is complete. Doesn't actually contribute to the solution as such.
public static class StringExtensions
{
public static bool StartsWithVocal(this string me)
{
return Regex.IsMatch(me, "^[aeiouAEIOU]");
}
}
Upvotes: 1