Covariance, generic, UserControl - c#

I have created a user control that contains an ObservableCollection<Something>. I learned that I cannot cast say ObservableCollection<Tiger> to ObservableCollection<Animal>. The solution I found was to add a helper class that handles all low level collection manipulation. My suspicion is that there is a more elegant solution and if so, maybe someone can point me into that direction.
See the code below that captures the problem and my solution. Zoo corresponds to the WPF UserControl. (Actually a zoo for one type od animal.) Ideally I would define it as Zoo<T> i.e. as a generic type but that would prevent me from using XAML. I need to define Animals as object in order assign to it.
class Program
{
public static void Main(string[] args)
{
Zoo zoo = new Zoo();
List<Tiger> tigers = new List<Tiger>() { new Tiger() };
zoo.Animals = tigers;
zoo.Helper = new TigerHelper(tigers);
Console.WriteLine(zoo.GetCount());
Console.ReadLine();
}
}
public class Animal { }
public class Tiger : Animal { }
public interface Helper { int GetCount(); }
public class TigerHelper : Helper
{
private List<Tiger> tigers;
public TigerHelper(List<Tiger> tigers) { this.tigers = tigers; }
public int GetCount() { return tigers.Count; }
}
public class Zoo
{
public object Animals { get; set; }
public Helper Helper { get; set; }
public int GetCount() { return Helper.GetCount(); }
}

Rather than go all the way down to object, you can use IList. This gives you access to most of the features of the list, but without the generics. For example, you can still access the Count property:
public class Zoo
{
public IList Animals { get; set; }
public Helper Helper { get; set; }
public int GetCount() { return Animals.Count; }
}

Related

c#: Interface needs to have a property off implementing class type

I need to have something like this. So a class that implements this Interface needs to get a property with the same type as the class.
Is this even possible, ifso how? I'm using .net 6.
public interface IProperty
{
public typeof(this) parameter { get; } // doesn't work, can't use typeof()
}
public class clsResourceProperty : IProperty
{
public clsResourceProperty parameter { get; }
}
public class clsInterfaceProperty : IProperty
{
public clsInterfaceProperty parameter { get; }
}
I know how to use generic interfaces, and with the second example it works, but clsResourcePropertyGeneric: IPropertyGeneric looks strange. And doens't work for the application i need.
public interface IPropertyGeneric<T>
{
public T parameter { get; }
}
public class clsResourcePropertyGeneric: IPropertyGeneric<clsResourcePropertyGeneric>
{
public clsResourcePropertyGeneric parameter { get; }
}
public class clsInterfacePropertyGeneric: IPropertyGeneric<clsInterfacePropertyGeneric>
{
public clsInterfacePropertyGeneric parameter { get; }
}
In the application i need, i need to have a class containing a list of this interface. So something like this:
public class clsState
{
public List<IProperty> data {get; private set;}
public clsState(List<IProperty> data)
{
this.data = data;
}
public void logic()
{
foreach(var d in data)
{
//do something with d.parameters
}
}
}
But this doesn't work with the generic interface. I need to make a class containing a list of this interface, where i define the generic type T. But this list can't contain ALL classes which implement this interface
public class clsState<T>
// need to add T here to use it in the list, but the list needs to contain ALL implementing class types, not only 1
{
public List<IProperty<T>> data {get; private set;}
public clsState(List<IProperty<T>> data)
{
this.data = data;
}
public void logic()
{
foreach(var d in data)
{
//do something with d.parameters
}
}
}
I found this link, but this is from 7 years ago, so maybe there is some evolution in this aspect?
You can use the interface as your property type, as in:
public interface IProperty
{
public IProperty parameter { get; }
}
public class clsResourceProperty : IProperty
{
public IProperty parameter { get; }
}
public class clsInterfaceProperty : IProperty
{
public IProperty parameter { get; }
}
As for having a collection of the interfaces, it is possible to collect all of the classes for a particular type or interface. This is from a piece of code in one of my libraries. It doesn't do exactly what you're after, but it might be a step towards your final solution.
private static Type[] strategyTypes;
private readonly static Type[] obsoleteTypes = new Type[]
{
};
static StrategyRepository()
{
strategyTypes = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.BaseType == typeof(Strategy))
.Except(obsoleteTypes)
.ToArray();
}
This question might be a more direct answer to that part of your question: Getting all types that implement an interface

Define a generic type constraint to be of the same type as the implementation

I wonder if it is possible to force constraint on interface or abstract class generic type to be the same as the concrete class that implements it specially for it.
Lets say we want to check a fitness of certain entity to task and make it comparable to others in their proficiency
abstract class Entity
{
public abstract int Fitness(); //Bigger the number - more fit the entity is
public int MoreFitThan(Entity other)
{
return Fitness().CompareTo(other.Fitness());
}
}
class Fish : Entity
{
public int swimSpeed { get; set; }
public override int Fitness()
{
return swimSpeed;
}
}
class Human : Entity
{
public int testPoints { get; set; }
public override int Fitness()
{
return testPoints;
}
}
But now we can compare fish's speed with human's test passing capability, which doesn't make sense.
static void Main()
{
Human human = new Human() {testPoints = 10};
Fish fish = new Fish() { swimSpeed = 20 };
fish.MoreFitThan(human);
}
So is there a general way make some kind of class or interface that would force it's children classes to implement only own type to own type comparison?
Like so we could only compare people with people and fish to fish, but without explicitly specifying the type of comparable entity?
You can force the type being passed to MoreFitThan to match the inheriting class by using generics in the following way.
abstract class Entity<T> where T : Entity<T>
{
public abstract int Fitness(); //Bigger the number - more fit the entity is
public int MoreFitThan(T other)
{
return Fitness().CompareTo(other.Fitness());
}
}
class Fish : Entity<Fish>
{
public int swimSpeed { get; set; }
public override int Fitness()
{
return swimSpeed;
}
}
class Human : Entity<Human>
{
public int testPoints { get; set; }
public override int Fitness()
{
return testPoints;
}
}
Then the following would be a compilation error
Human human = new Human() {testPoints = 10};
Fish fish = new Fish() { swimSpeed = 20 };
fish.MoreFitThan(human);
because Human is not a Fish. However this would allow a class that inherits from Fish to be compared to a Fish.
class Trout : Fish
{
public int size { get; set; }
public override int Fitness()
{
return size;
}
}
The following works because a Trout is a Fish.
Trout trout = new Trout() {size = 10};
Fish fish = new Fish() { swimSpeed = 20 };
fish.MoreFitThan(trout);
My suggestion would be to create classes of comparable types, say: Swimmer, Runner, Learner that implement your interface, then in those classes also implement IComparable and enforce the constraint on that class type. Then you can extend those classes with Human for Learner, Fish for Swimmer, etc...
There are other ways to do it, but this should work fine for your needs.

How do i use generic type in my base class?

I have a class structure with a base abstract class with derived classes.
My base class looks like this:
public abstract class Graph
{
public Dictionary<Vector3, int> Dictionary { private set; get; }
public List<T> List { set; get; }
public Graph()
{
Dictionary = new Dictionary<Vector3,int>();
}
}
Then i have 2 derived classes:
public class Graph_Waypoints : Graph
{
public Graph_Waypoints() : base ()
{
List = new List<Waypoint>();
}
}
public class Graph_Tiles : Graph
{
public Graph_Tiles() : base ()
{
List = new List<Tile>();
}
}
But it seems i cannot do flexible types for my graph like this. The idea here is to create a graph that lets me use different objects for its nodes. Whether it be a way-point graph or a tile based graph.
But i am struggling to work out how to get the flexibility for it to allow me change the type when i create each new graph.
Am i going in the right direction here ? How can i get the type flexibility on my list?
You're nearly there; you're just missing some key parts:
public abstract class Graph<T> // <-- Graph must be generic
{
public Dictionary<Vector3, int> Dictionary { private set; get; }
public List<T> List { set; get; }
public Graph()
{
Dictionary = new Dictionary<Vector3, int>();
// You could initialize the list as you did before, but it's cleaner to do it here
List = new List<T>();
}
}
public class Graph_Waypoints : Graph<Waypoint> // <-- Subclasses must provide the base class generic arguments
{
public Graph_Waypoints() : base()
{
}
}
public class Graph_Tiles : Graph<Tile>
{
public Graph_Tiles() : base()
{
}
}
Also note, you do not need to explicitly write : base() when implementing argument-less constructors; the compiler does it for you

Dynamic cast behavior in loop

I'm trying to accomplish some hacking & slashing and was wondering how to approach the following.
There are 2 interfaces defined:
public interface IBase
{
string Name { get; }
void Run();
}
public interface ISecondBase<T> : IEntityTask
{
Thing<T> Thing { get; }
}
Somewhere else I have a list of IBase.
This list is filled ISecondBase. I would like to be able to loop through the list of Base, but using some reflection tricks and hacks als be able to call Thing on the items. I know they're there, the compiler doesn't.
So I'd have to cast it to its concrete type at runtime, but this cast has to be dynamic, based on reflected information in the loop... So all type information is dynamic... I'm starting to think in circles :)
Since I know on beforehand that everything inside it is always of the SecondBase type, I decided to use the dynamic keyword and just let it resolve at runtime. This seems to me like an easy way out. Is there some best practice for these cases? Should I redesign, without loss of generality, and how?
foreach(var x in y)
{
dynamic melp = x;
melp.Thingy;
}
Where to start?
Edit: Perhaps some more code to make the example less contrived.
I have the base classes as mentioned. In real life they look like this:
public interface IEntityTask
{
string Name { get; }
void Run();
}
public interface IEntityTask<T> : IEntityTask
{
Task<T> Task { get; }
}
//Then there are classes that implement these:
public class CreateEntityTask<T> : IEntityTask<Guid>
{
public T Entity { get; private set; }
public Func<T, Guid> EntityMethod { get; private set; }
public Task<Guid> Task { get; private set; }
public void Run()
{
Task = Task<Guid>.Run(() => entityAccess.CreateEntity<T>(Entity, EntityMethod));
}
}
public class ReadEntityTask<T> : IEntityTask<T>
{
public Guid EntityId { get; private set; }
public Func<Guid, T> EntityMethod { get; private set; }
public Task<T> Task { get; private set; }
public void Run()
{
Task = Task<T>.Run(() => entityAccess.ReadEntity<T>(EntityId, EntityMethod));
}
}
//Furthermore there is a class called EntityTaskManager, which holds a list of these things and runs, awaits & collects the results on them.
public class EntityTaskManager
{
public List<IEntityTask> EntityTasks { get; set; } // I want tasks of Guid and bool in here!!!!
public Dictionary<string, object> EntityTaskResults { get; set; }
}
In a calling class I construct a new EntityTask and add it to the list. And then call RunTasks on the manager.
I'd modify IEntityTask like this:
public interface IEntityTask
{
string Name { get; }
void Run();
object Result { get; }
}
If EntityTaskManager is the only place, where you work with IEntityTask type, the implementation of Result would be explicit:
public class CreateEntityTask<T> : IEntityTask<Guid>
{
/* The rest of code here */
object IEntityTask.Result
{
get { return Task.Result; }
}
}
Then fetching task results should be trivial:
var results = entityTasksManager
.EntityTasks
.Select(t => t.Result);

Sorting a `List<object>` by object properties

I have some different objects that all of them have a integer field called Place. Is there a way to sort out this list without knowing what is the actual object? I mean just accessing the Place field and sort the list based on this number. possibly using linq or something?
some example objects:
public class Car
{
public int Place;
//Other related fields
}
public class Human
{
public int Place;
//Other related fields
}
//Somwhere in program
List<object> GameObjects;
You should derive your classes from a base class.
public class Base
{
public int Place;
}
public class Car : Base
{
// other properties
}
public class Human : Base
{
// other properties
}
Then you can create a list of your base type, add humans
and cars. After that you can use the Linq Sort or OrderBy method.
List<Base> list = new List<Base>();
list.Add(new Human { Place = 2 });
list.Add(new Car { Place = 1 });
var sortedList = list.Sort(x => x.Place);
More Information
The C# Station Tutorial - Lesson 8: Class Inheritance
MSDN - Queryable.OrderBy
MSDN - List.Sort Method
No because object doesn't have a Place property only Car/Human do.
There are a couple of ways you can solve this problem:
Introduce a base class
public class GameObject
{
public int Place { get; set; }
}
public class Car : GameObject
{}
public class Human : GameObject
{}
...
List<GameObject> GameObjects
Use a generic interface
public interface IGameObject
{
int Place { get; }
}
public class Car : IGameObject
{
public int Place { get; set; }
}
public class Human : IGameObject
{
public int Place { get; set; }
}
List<IGameObject> GameObjects
What you just discovered is relationship between those types. Both Car and Human seem to have a Place property, so you should extract an interface à la IGameObject.
The best way is to use an interface. If you can't, you still can do late binding using the dynamic keyword:
var list = new List<object>
{
new Car { Place = 3 },
new Human { Place = 1 },
new Car { Place = 2 }
};
var sortedList = list.OrderBy(o => ((dynamic)o).Place);
Yes, its possible using delegate methods with reflection. This is upto my knowledge, may be some other giants create it without using reflection
The best you can do is use an Interface, like this:
public Interface IFoo
{
int place;
}
And the implement that interface:
public class Car : IFoo
{
public int Place;
}
public class Human : IFoo
{
public int Place;
}
And then with linq:
List<IFoo> GameObjects;
GameObjects.OrderBy(g => g.Place);
You could let them implement an interface IPlaceable and use a property instead of only a field:
public interface IPlaceable
{
int Place { get; set; }
}
public class Car : IPlaceable
{
public int Place { get; set; }
//Other related fields
}
public class Human : IPlaceable
{
public int Place { get; set; }
//Other related fields
}
// Somwhere in program
List<IPlaceable> GameObjects;
// Somwhere else
GameObjects.OrderBy(go => go.Place);
Note that the list now is a List<IPlaceable> instead of a List<Object>.

Categories