Commit c70bc5d4 authored by Marc Gravell's avatar Marc Gravell

BREAKING CHANGE: KeyValuePair<,> is really confusing for talking about hashes...

BREAKING CHANGE: KeyValuePair<,> is really confusing for talking about hashes and sorted sets; this fixes that, but changes the API
parent 82a112c8
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
using NUnit.Framework;
namespace StackExchange.Redis.Tests
......@@ -56,9 +52,19 @@ public void SortedSetScan(bool supported)
var arr = db.SortedSetScan(key).ToArray();
Assert.AreEqual(3, arr.Length);
Assert.IsTrue(arr.Any(x => x.Key == "a" && x.Value == 1), "a");
Assert.IsTrue(arr.Any(x => x.Key == "b" && x.Value == 2), "b");
Assert.IsTrue(arr.Any(x => x.Key == "c" && x.Value == 3), "c");
Assert.IsTrue(arr.Any(x => x.Element == "a" && x.Score == 1), "a");
Assert.IsTrue(arr.Any(x => x.Element == "b" && x.Score == 2), "b");
Assert.IsTrue(arr.Any(x => x.Element == "c" && x.Score == 3), "c");
var dictionary = arr.ToDictionary();
Assert.AreEqual(1, dictionary["a"]);
Assert.AreEqual(2, dictionary["b"]);
Assert.AreEqual(3, dictionary["c"]);
var sDictionary = arr.ToStringDictionary();
Assert.AreEqual(1, sDictionary["a"]);
Assert.AreEqual(2, sDictionary["b"]);
Assert.AreEqual(3, sDictionary["c"]);
}
}
......@@ -80,9 +86,19 @@ public void HashScan(bool supported)
var arr = db.HashScan(key).ToArray();
Assert.AreEqual(3, arr.Length);
Assert.IsTrue(arr.Any(x => x.Key == "a" && x.Value == "1"), "a");
Assert.IsTrue(arr.Any(x => x.Key == "b" && x.Value == "2"), "b");
Assert.IsTrue(arr.Any(x => x.Key == "c" && x.Value == "3"), "c");
Assert.IsTrue(arr.Any(x => x.Name == "a" && x.Value == "1"), "a");
Assert.IsTrue(arr.Any(x => x.Name == "b" && x.Value == "2"), "b");
Assert.IsTrue(arr.Any(x => x.Name == "c" && x.Value == "3"), "c");
var dictionary = arr.ToDictionary();
Assert.AreEqual(1, (long)dictionary["a"]);
Assert.AreEqual(2, (long)dictionary["b"]);
Assert.AreEqual(3, (long)dictionary["c"]);
var sDictionary = arr.ToStringDictionary();
Assert.AreEqual("1", sDictionary["a"]);
Assert.AreEqual("2", sDictionary["b"]);
Assert.AreEqual("3", sDictionary["c"]);
}
}
......
......@@ -64,6 +64,8 @@
</ItemGroup>
<ItemGroup>
<Compile Include="StackExchange\Redis\Aggregate.cs" />
<Compile Include="StackExchange\Redis\ExtensionMethods.cs" />
<Compile Include="StackExchange\Redis\HashEntry.cs" />
<Compile Include="StackExchange\Redis\InternalErrorEventArgs.cs" />
<Compile Include="StackExchange\Redis\RedisChannel.cs" />
<Compile Include="StackExchange\Redis\Bitwise.cs" />
......@@ -139,6 +141,7 @@
<Compile Include="StackExchange\Redis\SocketManager.NoPoll.cs">
<DependentUpon>SocketManager.cs</DependentUpon>
</Compile>
<Compile Include="StackExchange\Redis\SortedSetEntry.cs" />
<Compile Include="StackExchange\Redis\SortType.cs" />
<Compile Include="StackExchange\Redis\StringSplits.cs" />
<Compile Include="StackExchange\Redis\TaskSource.cs" />
......
using System;
using System.Collections.Generic;
namespace StackExchange.Redis
{
/// <summary>
/// Utility methods
/// </summary>
public static class ExtensionMethods
{
/// <summary>
/// Create a dictionary from an array of HashEntry values
/// </summary>
public static Dictionary<string,string> ToStringDictionary(this HashEntry[] hash)
{
if (hash == null) return null;
var result = new Dictionary<string, string>(hash.Length, StringComparer.Ordinal);
for(int i = 0; i < hash.Length; i++)
{
result.Add(hash[i].name, hash[i].value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of HashEntry values
/// </summary>
public static Dictionary<RedisValue, RedisValue> ToDictionary(this HashEntry[] hash)
{
if (hash == null) return null;
var result = new Dictionary<RedisValue, RedisValue>(hash.Length);
for (int i = 0; i < hash.Length; i++)
{
result.Add(hash[i].name, hash[i].value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of SortedSetEntry values
/// </summary>
public static Dictionary<string, double> ToStringDictionary(this SortedSetEntry[] sortedSet)
{
if (sortedSet == null) return null;
var result = new Dictionary<string, double>(sortedSet.Length, StringComparer.Ordinal);
for (int i = 0; i < sortedSet.Length; i++)
{
result.Add(sortedSet[i].element, sortedSet[i].score);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of SortedSetEntry values
/// </summary>
public static Dictionary<RedisValue, double> ToDictionary(this SortedSetEntry[] sortedSet)
{
if (sortedSet == null) return null;
var result = new Dictionary<RedisValue, double>(sortedSet.Length);
for (int i = 0; i < sortedSet.Length; i++)
{
result.Add(sortedSet[i].element, sortedSet[i].score);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of key/value pairs
/// </summary>
public static Dictionary<string, string> ToStringDictionary(this KeyValuePair<RedisKey, RedisValue>[] pairs)
{
if (pairs == null) return null;
var result = new Dictionary<string, string>(pairs.Length, StringComparer.Ordinal);
for (int i = 0; i < pairs.Length; i++)
{
result.Add(pairs[i].Key, pairs[i].Value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of key/value pairs
/// </summary>
public static Dictionary<RedisKey, RedisValue> ToDictionary(this KeyValuePair<RedisKey, RedisValue>[] pairs)
{
if (pairs == null) return null;
var result = new Dictionary<RedisKey, RedisValue>(pairs.Length);
for (int i = 0; i < pairs.Length; i++)
{
result.Add(pairs[i].Key, pairs[i].Value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of string pairs
/// </summary>
public static Dictionary<string, string> ToDictionary(this KeyValuePair<string, string>[] pairs)
{
if (pairs == null) return null;
var result = new Dictionary<string, string>(pairs.Length, StringComparer.Ordinal);
for (int i = 0; i < pairs.Length; i++)
{
result.Add(pairs[i].Key, pairs[i].Value);
}
return result;
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace StackExchange.Redis
{
/// <summary>
/// Describes a hash-field (a name/value pair)
/// </summary>
public struct HashEntry : IEquatable<HashEntry>
{
internal readonly RedisValue name, value;
/// <summary>
/// Initializes a HashEntry value
/// </summary>
public HashEntry(RedisValue name, RedisValue value)
{
this.name = name;
this.value = value;
}
/// <summary>
/// The name of the hash field
/// </summary>
public RedisValue Name { get { return name; } }
/// <summary>
/// The value of the hash field
/// </summary>
public RedisValue Value{ get { return value; } }
/// <summary>
/// The name of the hash field
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Name", false)]
public RedisValue Key { get { return name; } }
/// <summary>
/// Converts to a key/value pair
/// </summary>
public static implicit operator KeyValuePair<RedisValue, RedisValue>(HashEntry value)
{
return new KeyValuePair<RedisValue, RedisValue>(value.name, value.value);
}
/// <summary>
/// Converts from a key/value pair
/// </summary>
public static implicit operator HashEntry(KeyValuePair<RedisValue, RedisValue> value)
{
return new HashEntry(value.Key, value.Value);
}
/// <summary>
/// See Object.ToString()
/// </summary>
public override string ToString()
{
return name + ": " + value;
}
/// <summary>
/// See Object.GetHashCode()
/// </summary>
public override int GetHashCode()
{
return name.GetHashCode() ^ value.GetHashCode();
}
/// <summary>
/// Compares two values for equality
/// </summary>
public override bool Equals(object obj)
{
return obj is HashEntry && Equals((HashEntry)obj);
}
/// <summary>
/// Compares two values for equality
/// </summary>
public bool Equals(HashEntry value)
{
return this.name == value.name && this.value == value.value;
}
}
}
......@@ -93,7 +93,7 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// </summary>
/// <returns>list of fields and their values stored in the hash, or an empty list when key does not exist.</returns>
/// <remarks>http://redis.io/commands/hgetall</remarks>
KeyValuePair<RedisValue, RedisValue>[] HashGetAll(RedisKey key, CommandFlags flags = CommandFlags.None);
HashEntry[] HashGetAll(RedisKey key, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Increments the number stored at field in the hash stored at key by increment. If key does not exist, a new key holding a hash is created. If field does not exist or holds a string that cannot be interpreted as integer, the value is set to 0 before the operation is performed.
......@@ -130,13 +130,13 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// </summary>
/// <returns>yields all elements of the hash.</returns>
/// <remarks>http://redis.io/commands/hscan</remarks>
IEnumerable<KeyValuePair<RedisValue, RedisValue>> HashScan(RedisKey key, RedisValue pattern = default(RedisValue), int pageSize = RedisDatabase.ScanUtils.DefaultPageSize, CommandFlags flags = CommandFlags.None);
IEnumerable<HashEntry> HashScan(RedisKey key, RedisValue pattern = default(RedisValue), int pageSize = RedisDatabase.ScanUtils.DefaultPageSize, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Sets the specified fields to their respective values in the hash stored at key. This command overwrites any existing fields in the hash. If key does not exist, a new key holding a hash is created.
/// </summary>
/// <remarks>http://redis.io/commands/hmset</remarks>
void HashSet(RedisKey key, KeyValuePair<RedisValue, RedisValue>[] hashFields, CommandFlags flags = CommandFlags.None);
void HashSet(RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Sets field in the hash stored at key to value. If key does not exist, a new key holding a hash is created. If field already exists in the hash, it is overwritten.
......@@ -555,7 +555,7 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// </summary>
/// <returns>The number of elements added to the sorted sets, not including elements already existing for which the score was updated.</returns>
/// <remarks>http://redis.io/commands/zadd</remarks>
long SortedSetAdd(RedisKey key, KeyValuePair<RedisValue, double>[] values, CommandFlags flags = CommandFlags.None);
long SortedSetAdd(RedisKey key, SortedSetEntry[] values, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Computes a set operation over two sorted sets, and stores the result in destination, optionally performing
......@@ -612,7 +612,7 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <returns>list of elements in the specified range</returns>
/// <remarks>http://redis.io/commands/zrange</remarks>
/// <remarks>http://redis.io/commands/zrevrange</remarks>
KeyValuePair<RedisValue, double>[] SortedSetRangeByRankWithScores(RedisKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);
SortedSetEntry[] SortedSetRangeByRankWithScores(RedisKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Returns the specified range of elements in the sorted set stored at key. By default the elements are considered to be ordered from the lowest to the highest score. Lexicographical order is used for elements with equal score.
......@@ -633,7 +633,7 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <returns>list of elements in the specified score range</returns>
/// <remarks>http://redis.io/commands/zrangebyscore</remarks>
/// <remarks>http://redis.io/commands/zrevrangebyscore</remarks>
KeyValuePair<RedisValue, double>[] SortedSetRangeByScoreWithScores(RedisKey key,
SortedSetEntry[] SortedSetRangeByScoreWithScores(RedisKey key,
double start = double.NegativeInfinity, double stop = double.PositiveInfinity,
Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1,
CommandFlags flags = CommandFlags.None);
......@@ -679,7 +679,7 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// </summary>
/// <returns>yields all elements of the sorted set.</returns>
/// <remarks>http://redis.io/commands/zscan</remarks>
IEnumerable<KeyValuePair<RedisValue, double>> SortedSetScan(RedisKey key, RedisValue pattern = default(RedisValue), int pageSize = RedisDatabase.ScanUtils.DefaultPageSize, CommandFlags flags = CommandFlags.None);
IEnumerable<SortedSetEntry> SortedSetScan(RedisKey key, RedisValue pattern = default(RedisValue), int pageSize = RedisDatabase.ScanUtils.DefaultPageSize, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Returns the score of member in the sorted set at key; If member does not exist in the sorted set, or key does not exist, nil is returned.
/// </summary>
......
......@@ -58,7 +58,7 @@ public interface IDatabaseAsync : IRedisAsync
/// </summary>
/// <returns>list of fields and their values stored in the hash, or an empty list when key does not exist.</returns>
/// <remarks>http://redis.io/commands/hgetall</remarks>
Task<KeyValuePair<RedisValue, RedisValue>[]> HashGetAllAsync(RedisKey key, CommandFlags flags = CommandFlags.None);
Task<HashEntry[]> HashGetAllAsync(RedisKey key, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Returns the value associated with field in the hash stored at key.
......@@ -109,7 +109,7 @@ public interface IDatabaseAsync : IRedisAsync
/// Sets the specified fields to their respective values in the hash stored at key. This command overwrites any existing fields in the hash. If key does not exist, a new key holding a hash is created.
/// </summary>
/// <remarks>http://redis.io/commands/hmset</remarks>
Task HashSetAsync(RedisKey key, KeyValuePair<RedisValue, RedisValue>[] hashFields, CommandFlags flags = CommandFlags.None);
Task HashSetAsync(RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Sets field in the hash stored at key to value. If key does not exist, a new key holding a hash is created. If field already exists in the hash, it is overwritten.
......@@ -527,7 +527,7 @@ public interface IDatabaseAsync : IRedisAsync
/// </summary>
/// <returns>The number of elements added to the sorted sets, not including elements already existing for which the score was updated.</returns>
/// <remarks>http://redis.io/commands/zadd</remarks>
Task<long> SortedSetAddAsync(RedisKey key, KeyValuePair<RedisValue, double>[] values, CommandFlags flags = CommandFlags.None);
Task<long> SortedSetAddAsync(RedisKey key, SortedSetEntry[] values, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Computes a set operation over two sorted sets, and stores the result in destination, optionally performing
......@@ -584,7 +584,7 @@ public interface IDatabaseAsync : IRedisAsync
/// <returns>list of elements in the specified range</returns>
/// <remarks>http://redis.io/commands/zrange</remarks>
/// <remarks>http://redis.io/commands/zrevrange</remarks>
Task<KeyValuePair<RedisValue, double>[]> SortedSetRangeByRankWithScoresAsync(RedisKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);
Task<SortedSetEntry[]> SortedSetRangeByRankWithScoresAsync(RedisKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Returns the specified range of elements in the sorted set stored at key. By default the elements are considered to be ordered from the lowest to the highest score. Lexicographical order is used for elements with equal score.
......@@ -605,7 +605,7 @@ public interface IDatabaseAsync : IRedisAsync
/// <returns>list of elements in the specified score range</returns>
/// <remarks>http://redis.io/commands/zrangebyscore</remarks>
/// <remarks>http://redis.io/commands/zrevrangebyscore</remarks>
Task<KeyValuePair<RedisValue, double>[]> SortedSetRangeByScoreWithScoresAsync(RedisKey key,
Task<SortedSetEntry[]> SortedSetRangeByScoreWithScoresAsync(RedisKey key,
double start = double.NegativeInfinity, double stop = double.PositiveInfinity,
Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1,
CommandFlags flags = CommandFlags.None);
......
......@@ -69,8 +69,8 @@ abstract class ResultProcessor
public static readonly ResultProcessor<RedisResult>
ScriptResult = new ScriptResultProcessor();
public static readonly SortedSetWithScoresProcessor
SortedSetWithScores = new SortedSetWithScoresProcessor();
public static readonly SortedSetEntryArrayProcessor
SortedSetWithScores = new SortedSetEntryArrayProcessor();
public static readonly ResultProcessor<string>
String = new StringProcessor(),
......@@ -80,8 +80,8 @@ public static readonly SortedSetWithScoresProcessor
public static readonly TimeSpanProcessor
TimeSpanFromMilliseconds = new TimeSpanProcessor(true),
TimeSpanFromSeconds = new TimeSpanProcessor(false);
public static readonly ValuePairInterleavedProcessor
ValuePairInterleaved = new ValuePairInterleavedProcessor();
public static readonly HashEntryArrayProcessor
HashEntryArray = new HashEntryArrayProcessor();
static readonly byte[] MOVED = Encoding.UTF8.GetBytes("MOVED "), ASK = Encoding.UTF8.GetBytes("ASK ");
public void ConnectionFail(Message message, ConnectionFailureType fail, Exception innerException)
......@@ -342,27 +342,28 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes
}
}
internal sealed class SortedSetWithScoresProcessor : ValuePairInterleavedProcessorBase<RedisValue, double>
internal sealed class SortedSetEntryArrayProcessor : ValuePairInterleavedProcessorBase<SortedSetEntry>
{
protected override RedisValue ParseKey(RawResult key) { return key.AsRedisValue(); }
protected override double ParseValue(RawResult value)
protected override SortedSetEntry Parse(RawResult first, RawResult second)
{
double val;
return value.TryGetDouble(out val) ? val : double.NaN;
return new SortedSetEntry(first.AsRedisValue(), second.TryGetDouble(out val) ? val : double.NaN);
}
}
internal sealed class ValuePairInterleavedProcessor : ValuePairInterleavedProcessorBase<RedisValue, RedisValue>
internal sealed class HashEntryArrayProcessor : ValuePairInterleavedProcessorBase<HashEntry>
{
protected override RedisValue ParseKey(RawResult key) { return key.AsRedisValue(); }
protected override RedisValue ParseValue(RawResult key) { return key.AsRedisValue(); }
protected override HashEntry Parse(RawResult first, RawResult second)
{
return new HashEntry(first.AsRedisValue(), second.AsRedisValue());
}
}
internal abstract class ValuePairInterleavedProcessorBase<TKey, TValue> : ResultProcessor<KeyValuePair<TKey, TValue>[]>
internal abstract class ValuePairInterleavedProcessorBase<T> : ResultProcessor<T[]>
{
static readonly KeyValuePair<TKey, TValue>[] nix = new KeyValuePair<TKey, TValue>[0];
static readonly T[] nix = new T[0];
public bool TryParse(RawResult result, out KeyValuePair<TKey, TValue>[] pairs)
public bool TryParse(RawResult result, out T[] pairs)
{
switch (result.Type)
{
......@@ -381,13 +382,11 @@ public bool TryParse(RawResult result, out KeyValuePair<TKey, TValue>[] pairs)
}
else
{
pairs = new KeyValuePair<TKey, TValue>[count];
pairs = new T[count];
int offset = 0;
for (int i = 0; i < pairs.Length; i++)
{
var setting = ParseKey(arr[offset++]);
var value = ParseValue(arr[offset++]);
pairs[i] = new KeyValuePair<TKey, TValue>(setting, value);
pairs[i] = Parse(arr[offset++], arr[offset++]);
}
}
}
......@@ -397,11 +396,10 @@ public bool TryParse(RawResult result, out KeyValuePair<TKey, TValue>[] pairs)
return false;
}
}
protected abstract TKey ParseKey(RawResult key);
protected abstract TValue ParseValue(RawResult value);
protected abstract T Parse(RawResult first, RawResult second);
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
{
KeyValuePair<TKey, TValue>[] arr;
T[] arr;
if (TryParse(result, out arr))
{
SetResult(message, arr);
......@@ -1004,10 +1002,12 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes
}
}
sealed class StringPairInterleavedProcessor : ValuePairInterleavedProcessorBase<string, string>
sealed class StringPairInterleavedProcessor : ValuePairInterleavedProcessorBase<KeyValuePair<string, string>>
{
protected override string ParseKey(RawResult key) { return key.GetString(); }
protected override string ParseValue(RawResult key) { return key.GetString(); }
protected override KeyValuePair<string, string> Parse(RawResult first, RawResult second)
{
return new KeyValuePair<string, string>(first.GetString(), second.GetString());
}
}
sealed class StringProcessor : ResultProcessor<string>
......
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace StackExchange.Redis
{
/// <summary>
/// Describes a sorted-set element with the corresponding value
/// </summary>
public struct SortedSetEntry : IEquatable<SortedSetEntry>, IComparable, IComparable<SortedSetEntry>
{
internal readonly RedisValue element;
internal readonly double score;
/// <summary>
/// Initializes a SortedSetEntry value
/// </summary>
public SortedSetEntry(RedisValue element, double score)
{
this.element = element;
this.score = score;
}
/// <summary>
/// The unique element stored in the sorted set
/// </summary>
public RedisValue Element { get { return element; } }
/// <summary>
/// The score against the element
/// </summary>
public double Score { get { return score; } }
/// <summary>
/// The score against the element
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Score", false)]
public double Value { get { return score; } }
/// <summary>
/// The unique element stored in the sorted set
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Element", false)]
public RedisValue Key { get { return element; } }
/// <summary>
/// Converts to a key/value pair
/// </summary>
public static implicit operator KeyValuePair<RedisValue,double>(SortedSetEntry value)
{
return new KeyValuePair<RedisValue, double>(value.element, value.score);
}
/// <summary>
/// Converts from a key/value pair
/// </summary>
public static implicit operator SortedSetEntry(KeyValuePair<RedisValue, double> value)
{
return new SortedSetEntry(value.Key, value.Value);
}
/// <summary>
/// See Object.ToString()
/// </summary>
public override string ToString()
{
return element + ": " + score;
}
/// <summary>
/// See Object.GetHashCode()
/// </summary>
public override int GetHashCode()
{
return element.GetHashCode() ^ score.GetHashCode();
}
/// <summary>
/// Compares two values for equality
/// </summary>
public override bool Equals(object obj)
{
return obj is SortedSetEntry && Equals((SortedSetEntry)obj);
}
/// <summary>
/// Compares two values for equality
/// </summary>
public bool Equals(SortedSetEntry value)
{
return this.element == value.element && this.score == value.score;
}
/// <summary>
/// Compares two values by score
/// </summary>
public int CompareTo(SortedSetEntry value)
{
return this.score.CompareTo(value.score);
}
/// <summary>
/// Compares two values by score
/// </summary>
public int CompareTo(object value)
{
return value is SortedSetEntry ? CompareTo((SortedSetEntry)value) : -1;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment