C
C#4mo ago
Pagano

Custom Made Collection

I guess this is a real stupid question but how do I create my own custom collection? I have a Player class and I need to create a custom class that is a Collection of Player with other fields and methods but how do I implement my own collection in .NET Core? If I had to guess, I would say implement IEnumerable<T> and IEnumerator<T> but I don't know how to implement them either. Can I have some help please? I can provide with a more in-depth of the idea and my classes if needed.
58 Replies
Angius
Angius4mo ago
Just implement the interface you need or inherit from the type you want, yes Inheritance might be easier in this case, if you don't need to add much
Pagano
Pagano4mo ago
Can I have an example? The problem is that I need a Collection that acts like a Queue in the sense of FIFO but I need to be able to remove Player at any position and have all LINQ methods like First<>(), Any<>() etc (It won't be a generic collection tho)
MODiX
MODiX4mo ago
Angius
REPL Result: Success
record Person(string Name, int Age);
class Peeps : List<Person>
{
public int TotalAge => this.Sum(p => p.Age);
}

var people = new Peeps {
new("Bob", 42),
new("Anna", 17),
};

people.Add(new Person("Hank", 78));

people.TotalAge
record Person(string Name, int Age);
class Peeps : List<Person>
{
public int TotalAge => this.Sum(p => p.Age);
}

var people = new Peeps {
new("Bob", 42),
new("Anna", 17),
};

people.Add(new Person("Hank", 78));

people.TotalAge
Result: int
137
137
Compile: 508.740ms | Execution: 75.859ms | React with ❌ to remove this embed.
Pagano
Pagano4mo ago
But that doesn't guarantee order of insertion right?
Angius
Angius4mo ago
No, you would need a sorted collection to guarantee order
Pagano
Pagano4mo ago
So what would you recommend?
Angius
Angius4mo ago
SortedList
Pagano
Pagano4mo ago
And I can do the same? Just add more fields if needed and methods?
Angius
Angius4mo ago
You could also inherit Queue if you need a queue as you say And have it implement IList to get .Add() etc
Pagano
Pagano4mo ago
The queue was just so I have a FIFO collection I need a Collection that has the FIFO property, can remove people at any index in the collection, maintains insertion order and can be modified if needed In that case I inherit Queue and IList or SortedList only should work?
Angius
Angius4mo ago
Queue should ensure order, and gives you FIFO, so that's an obvious choice, yeah IList for adding and removing at arbitrary points
Pagano
Pagano4mo ago
So instead of doing my Custom Collection I just implement and adapt?
Angius
Angius4mo ago
Well, this will be your custom collection
Pagano
Pagano4mo ago
I mean, I don't need to do from scratch implementing only IEnumerable and IEnumerator
Angius
Angius4mo ago
Yeah
Pagano
Pagano4mo ago
Ok Tysm Is there any tutorial or document that help me understand what each method implementation should look like?
Angius
Angius4mo ago
No description
Pagano
Pagano4mo ago
But how do I implement them on top of the Queue I inherited?
Angius
Angius4mo ago
Queue implements IEnumerable You can use that
Pagano
Pagano4mo ago
Because the Class is like this:
public class EvoHubQueue : Queue<Player>, IList<Player>
{
public Player this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

public bool IsReadOnly => throw new NotImplementedException();

public void Add(Player item)
{
throw new NotImplementedException();
}

public int IndexOf(Player item)
{
throw new NotImplementedException();
}

public void Insert(int index, Player item)
{
throw new NotImplementedException();
}

public bool Remove(Player item)
{
throw new NotImplementedException();
}

public void RemoveAt(int index)
{
throw new NotImplementedException();
}
}
public class EvoHubQueue : Queue<Player>, IList<Player>
{
public Player this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

public bool IsReadOnly => throw new NotImplementedException();

public void Add(Player item)
{
throw new NotImplementedException();
}

public int IndexOf(Player item)
{
throw new NotImplementedException();
}

public void Insert(int index, Player item)
{
throw new NotImplementedException();
}

public bool Remove(Player item)
{
throw new NotImplementedException();
}

public void RemoveAt(int index)
{
throw new NotImplementedException();
}
}
Angius
Angius4mo ago
Or... huh I wonder if it would be easier to just skip the queue, back your collection with an array or some such, and just add whatever methods you need Like, I assume, Dequeue() Arrays, IIRC, do have a guaranteed order of elements
Pagano
Pagano4mo ago
Wait, I don't think I follow the new idea
Angius
Angius4mo ago
public class MyCollection : IList<Player>
{
private Player[] _players = [];

// implement IList

public Player Dequeue()
{
var player = _players[0];
RemoveAt(0);
return player;
}
}
public class MyCollection : IList<Player>
{
private Player[] _players = [];

// implement IList

public Player Dequeue()
{
var player = _players[0];
RemoveAt(0);
return player;
}
}
Something like that, I'd imagine
Pagano
Pagano4mo ago
But then I wouldn't have assured order of insertion, right? I would have FIFO tho
Angius
Angius4mo ago
Why would the order not be assured? You'd be able to implement .Add() however you want
Pagano
Pagano4mo ago
Because you are using an IList
Angius
Angius4mo ago
But what actually stores the data is an array Actually, pretty sure even a List is ordered
Pagano
Pagano4mo ago
I could just use the SortedList right?
Angius
Angius4mo ago
You could, yeah
Pagano
Pagano4mo ago
Sorry but how do I inherit SortedList but of type Player? Because it says it has a Key and a Value?
Angius
Angius4mo ago
The key could be an integer, for example The key is what it's sorted by
Pagano
Pagano4mo ago
So like an index?
Angius
Angius4mo ago
Yeah
Pagano
Pagano4mo ago
So like this for example?
public class EvoHubQueue : SortedList<int, Player>
{
public Player Pop()
{
Player player = this[0];
this.RemoveAt(0);
return player;
}
}
public class EvoHubQueue : SortedList<int, Player>
{
public Player Pop()
{
Player player = this[0];
this.RemoveAt(0);
return player;
}
}
Angius
Angius4mo ago
That could work, yeah
Pagano
Pagano4mo ago
But thats what you had in mind about altering its functions? And thats how you would implement?
Angius
Angius4mo ago
What I had in mind talking about altering functions, is that you have full control over what does what. You could have .Add() insert the item at a random index, or you could have .Remove() duplicate every item Wouldn't make much sense, but you could do it As for the above code, yeah, that's probably how I'd do it if I needed a sorted collection with a .Pop()
Pagano
Pagano4mo ago
Ok, Ill try to implement it more tysm
applejacks
applejacks4mo ago
wait, I'm confused here. you're talking about ensuring the order of insertion via FIFO, and using a sortedlist
Pagano
Pagano4mo ago
No, I needed a collection that had the properties I mentioned And if I had to create one from scratch, how should I But I think just creating a collection that inherits from SortedList with extra methods is going to work fine
applejacks
applejacks4mo ago
a sorted list ensures, regardless of the order you add items, the values are sorted by key
Pagano
Pagano4mo ago
I actually ended up with this by now:
public class EvoHubQueue : SortedSet<Player>
{
public required LeagueRoles Role { get; init; }

public Player Pop()
{
Player player = this.ElementAt(0);
this.Remove(player);
return player;
}
}
public class EvoHubQueue : SortedSet<Player>
{
public required LeagueRoles Role { get; init; }

public Player Pop()
{
Player player = this.ElementAt(0);
this.Remove(player);
return player;
}
}
applejacks
applejacks4mo ago
but then you can't insert at a given index... have you tested what you're trying to do? using a sortedset just means you have some other functionality to maintain the order of your Player list.
Pagano
Pagano4mo ago
I need to maintain the order and I don't need to insert in the middle or first position Always in the last
applejacks
applejacks4mo ago
you want to use a queue with remove at functionality, I'd implement a class that internally has a queue and, when remove at is called in my class, turn the queue into an array to get how many items exist after the index to be removed, dequeue them to a local var, dequeue the one i don't want and requeue them.
Pagano
Pagano4mo ago
Isn't that less efficient? May I ask how to implement an Intersect method for my class that has a target parameter that is another IEnumerable of the same type and a delegate that is what field I am comparing? This is the method:
public IEnumerable<Player> Intersect(IEnumerable<Player> targets, secondParam)
{

}
public IEnumerable<Player> Intersect(IEnumerable<Player> targets, secondParam)
{

}
What is the second param? I am confused
applejacks
applejacks4mo ago
less efficient than what? I'm driving now but I'm pretty sure, if you implement your code as is, insert 5 players in a given order then remove the middle one and add it back in and look at the order of your players. then add the exact same 5 players in a different order, remove the middle and add it back at the end. you'll see the order of the list of your players is the same
Pagano
Pagano4mo ago
Than using a SortedList as the only method I need that relates it to a Queue is the Dequeue as SortedList Add() already inserts in the last index right?
applejacks
applejacks4mo ago
no Add will add your item, then internally sort it's indexes to match the order of your keys
Pagano
Pagano4mo ago
So it doesn't maintain order of insertion?
applejacks
applejacks4mo ago
so if it's an <int, Player> and you pass (2, Apple), (4, Jacks), (3, Tomato soup), the order will be (2, Apple), (3, Tomato soup), (4, Jacks) ok. I'm moving now. but just test this, I'm like 90% sure I'm right.
Pagano
Pagano4mo ago
I am using SortedSet<Player> I don't have an index so wouldn't it ensure that? Ok
applejacks
applejacks4mo ago
85%. I've never used a sortedlist and it doesn't sound like what you need either
Pagano
Pagano4mo ago
Ok I see it now Does a normal HashSet<T> guarantees order of insertion? Nevermind A normal List<T> should work then? 🤔 Ok, I ended up with this so far and it seems to work:
public required LeagueRoles Role { get; init; }

public new void Add(Player player)
{
if (!this.Contains(player))
base.Add(player);
}

public Player Pop()
{
Player player = this.ElementAt(0);
this.Remove(player);
return player;
}
}
public required LeagueRoles Role { get; init; }

public new void Add(Player player)
{
if (!this.Contains(player))
base.Add(player);
}

public Player Pop()
{
Player player = this.ElementAt(0);
this.Remove(player);
return player;
}
}
But I would need help with this
Pagano
Pagano4mo ago
I ended up doing it this way but I didn't have time to test it yet:
public IEnumerable<Player> Intersect(IEnumerable<Player> targets)
{
var intersectedPlayers = new List<Player>();
foreach (var player in this)
{
foreach (var otherPlayer in targets)
{
if (0.7 * player.SkillRating.SkillRating <= otherPlayer.SkillRating.SkillRating * 1.3
&& 07 * otherPlayer.SkillRating.SkillRating <= player.SkillRating.SkillRating * 1.3)
{
intersectedPlayers.Add(otherPlayer);
}
}
}

return intersectedPlayers;
}
public IEnumerable<Player> Intersect(IEnumerable<Player> targets)
{
var intersectedPlayers = new List<Player>();
foreach (var player in this)
{
foreach (var otherPlayer in targets)
{
if (0.7 * player.SkillRating.SkillRating <= otherPlayer.SkillRating.SkillRating * 1.3
&& 07 * otherPlayer.SkillRating.SkillRating <= player.SkillRating.SkillRating * 1.3)
{
intersectedPlayers.Add(otherPlayer);
}
}
}

return intersectedPlayers;
}
As the way to compare two Lists and Players will always be this way
Want results from more Discord servers?
Add your server