Namespaces Required:
Class:
Example if using the selector to store clients:
Adding a client:
Getting a client from UID:
Getting a client from name:
Contains a client from an uid:
Contains a client from a name:
Contains a client from well... client.
Remove a client from UID:
Remove a client from name: (Please read the commenting at the UID removing)
Clear the collection:
Never seen anything like this being used a single source, although it would be common to have something like that and I was in need for it in my source, so wrapped it up pretty quickly, but I hope you like it.
And pro4never said he wanted some test on it to see if it was worth it.
Well I just went ahead and did a test, here is the result:
A bit surprised about the concurrent Dictionary, because I didn't though it'd be that slow compared to a regular dictionary o:
If you ask me it's worth it lmao.
Screenshot:
[Only registered and activated users can see links. Click Here To Register...]
Test:
Code:
using System.Collections.Concurrent;
Code:
public class Selector<TKey1, TKey2, TValue>
{
private ConcurrentDictionary<TKey1, TValue> selectorCollection1;
private ConcurrentDictionary<TKey2, TValue> selectorCollection2;
private ConcurrentDictionary<TKey1, TKey2> keymatcher1;
private ConcurrentDictionary<TKey2, TKey1> keymatcher2;
public Selector()
{
selectorCollection1 = new ConcurrentDictionary<TKey1, TValue>();
selectorCollection2 = new ConcurrentDictionary<TKey2, TValue>();
keymatcher1 = new ConcurrentDictionary<TKey1, TKey2>();
keymatcher2 = new ConcurrentDictionary<TKey2, TKey1>();
}
public bool TrySelect(TKey1 key, out TValue value)
{
return selectorCollection1.TryGetValue(key, out value);
}
public bool TrySelect(TKey2 key, out TValue value)
{
return selectorCollection2.TryGetValue(key, out value);
}
public bool TryAdd(TKey1 key1, TKey2 key2, TValue value)
{
return (selectorCollection1.TryAdd(key1, value) &&
selectorCollection2.TryAdd(key2, value) &&
keymatcher1.TryAdd(key1, key2) &&
keymatcher2.TryAdd(key2, key1));
}
public bool TryRemove(TKey1 key1)
{
TKey2 key2;
if (!keymatcher1.TryGetValue(key1, out key2))
return false;
TValue rval;
return (selectorCollection1.TryRemove(key1, out rval) &&
selectorCollection2.TryRemove(key2, out rval) &&
keymatcher1.TryRemove(key1, out key2) &&
keymatcher2.TryRemove(key2, out key1));
}
public bool TryRemove(TKey2 key2)
{
TKey1 key1;
if (!keymatcher2.TryGetValue(key2, out key1))
return false;
TValue rval;
return (selectorCollection1.TryRemove(key1, out rval) &&
selectorCollection2.TryRemove(key2, out rval) &&
keymatcher1.TryRemove(key1, out key2) &&
keymatcher2.TryRemove(key2, out key1));
}
public bool Contains(TKey1 key1)
{
return keymatcher1.ContainsKey(key1);
}
public bool Contains(TKey2 key2)
{
return keymatcher2.ContainsKey(key2);
}
public bool Contains(TValue value)
{
return selectorCollection1.Values.Contains(value);
}
public void Clear()
{
selectorCollection1.Clear();
selectorCollection2.Clear();
keymatcher1.Clear();
keymatcher2.Clear();
}
}
Code:
Selector<uint, string, GameClient> Clients; // uint is for the UID, string is for the name and GameClient is the client...
Code:
if (!Clients.TryAdd(client.UID, client.Name, client))
throw new Exception("Could not add the client.");
Code:
if (!Clients.TrySelect(1000000, out client)) // get from UID
throw new Exception("Could not get the client from UID.");
Code:
if (!Clients.TrySelect("Test", out client)) // get from name
throw new Exception("Could not get the client from name.");
Code:
if (Clients.Contains(1000000))
{
// a client with the uid 1000000 is existing
}
Code:
if (Clients.Contains("Test"))
{
// a client with the name Test is existing
}
Code:
if (Clients.Contains(client))
{
// the selector already contains the client
}
Code:
int tries = 0; while (!Clients.TryRemove(1000000) && (tries++ < 3)) // attempts to remove a client from the uid 1000000 System.Threading.Thread.Sleep(100); // the while loop is to make sure it will try to remove it again if it failed, most likely never will
Code:
int tries = 0;
while (!Clients.TryRemove("Test") && (tries++ < 3)) // attempts to remove a client from the name Test
System.Threading.Thread.Sleep(100);
Code:
Clients.Clear();
And pro4never said he wanted some test on it to see if it was worth it.
Well I just went ahead and did a test, here is the result:
A bit surprised about the concurrent Dictionary, because I didn't though it'd be that slow compared to a regular dictionary o:
If you ask me it's worth it lmao.
Screenshot:
[Only registered and activated users can see links. Click Here To Register...]
Test:
Code:
#region Regular Dictionary Test
System.Collections.Generic.Dictionary<uint, GameClient> d_clients = new System.Collections.Generic.Dictionary<uint, Program.GameClient>();
foreach (GameClient _client in clients)
d_clients.Add(_client.UID, _client);
Console.WriteLine("Beginning first test: System.Collections.Generic.Dictionary<TKey, TValue>");
Console.WriteLine("Started with 1000000 searches (Running 3 tests)...");
for (int tests = 0; tests < 3; tests++)
{
Stopwatch overall = new Stopwatch();
overall.Start();
int namecounter = 0;
for (int runs = 0; runs < 1000000; runs++)
{
string names = namesearches[namecounter];
foreach (GameClient client in d_clients.Values)
{
if (client.Name == names)
break;
}
namecounter++;
if (namecounter >= 500)
namecounter = 0;
}
Console.WriteLine("Finished test #{0} in {1} milliseconds...", tests, overall.ElapsedMilliseconds);
overall.Stop();
}
#endregion
#region Concurrent Dictionary Test
ConcurrentDictionary<uint, GameClient> c_clients = new ConcurrentDictionary<uint, Program.GameClient>();
foreach (GameClient _client in clients)
c_clients.TryAdd(_client.UID, _client);
Console.WriteLine("Beginning first test: System.Collections.Concurrent.Dictionary<TKey, TValue>");
Console.WriteLine("Started with 1000000 searches (Running 3 tests)...");
for (int tests = 0; tests < 3; tests++)
{
Stopwatch overall = new Stopwatch();
overall.Start();
int namecounter = 0;
for (int runs = 0; runs < 1000000; runs++)
{
string names = namesearches[namecounter];
foreach (GameClient client in c_clients.Values)
{
if (client.Name == names)
break;
}
namecounter++;
if (namecounter >= 500)
namecounter = 0;
}
Console.WriteLine("Finished test #{0} in {1} milliseconds...", tests, overall.ElapsedMilliseconds);
overall.Stop();
}
#endregion
#region Selector Dictionary Test
Selector<uint, string, GameClient> s_clients = new Selector<uint, string, Program.GameClient>();
foreach (GameClient _client in clients)
s_clients.TryAdd(_client.UID, _client.Name, _client);
Console.WriteLine("Beginning first test: Selector<TKey1, TKey2, TValue>");
Console.WriteLine("Started with 1000000 searches (Running 3 tests)...");
for (int tests = 0; tests < 3; tests++)
{
Stopwatch overall = new Stopwatch();
overall.Start();
int namecounter = 0;
int fails = 0;
for (int runs = 0; runs < 1000000; runs++)
{
string names = namesearches[namecounter];
GameClient client;
if (!s_clients.TrySelect(names, out client))
fails++;
namecounter++;
if (namecounter >= 500)
namecounter = 0;
}
Console.WriteLine("Selector fails: {0}", fails);
Console.WriteLine("Finished test #{0} in {1} milliseconds...", tests, overall.ElapsedMilliseconds);
overall.Stop();
}
#endregion