Problem with IDictionary<Complex Key, Complex Value>.Remove() implementation - c#

Hi I don't understand why this code doesn't work - it don't remove key; I still get "2" on output.
Bencode.BencodeDict d = new myTorrent.Bencode.BencodeDict();
d.Dict.Add(new Bencode.BencodeString("info"), new Bencode.BencodeString("1"));
d.Dict.Add(new Bencode.BencodeString("info2"), new Bencode.BencodeString("2"));
d.Dict.Add(new Bencode.BencodeString("info3"), new Bencode.BencodeString("3"));
d.Remove(new Bencode.BencodeString("info2"));
Bencode.BencodeVariable s1;
s1 = d[new Bencode.BencodeString("info2")];
if (s1 != null)
Console.WriteLine(System.Text.UTF8Encoding.UTF8.GetString(s1.Encode()));
My BencodeDict and BencodeString
namespace myTorrent.Bencode
{
class BencodeDict : BencodeVariable, IDictionary<BencodeString, BencodeVariable>
{
private Dictionary<BencodeString, BencodeVariable> dict;
public BencodeDict() {
this.dict = new Dictionary<BencodeString,BencodeVariable>();
}
protected override void InternalDecode(BinaryReader data) { /*...*/ }
public override long ByteLength() { /*...*/ }
public override byte[] Encode() { /*...*/ }
//#region Overridden Methods
public override bool Equals(object ob)
{
if (ob == null)
return false;
BencodeDict y = ob as BencodeDict;
if (this.dict.Count != y.dict.Count)
return false;
BencodeVariable val;
foreach (KeyValuePair<BencodeString, BencodeVariable> keypair in this.dict)
{
if (!y.TryGetValue(keypair.Key, out val))
return false;
if (!keypair.Value.Equals(val))
return false;
}
return true;
}
public override int GetHashCode()
{
int result = 0;
foreach (KeyValuePair<BencodeString, BencodeVariable> keypair in this.dict)
{
result ^= keypair.Key.GetHashCode();
result ^= keypair.Value.GetHashCode();
}
return result;
}
#region IDictionary and IList methods
public void Add(BencodeString key, BencodeVariable value)
{
this.dict.Add(key, value);
}
public void Add(KeyValuePair<BencodeString, BencodeVariable> item)
{
this.dict.Add(item.Key, item.Value);
}
public void Clear()
{
this.dict.Clear();
}
public bool Contains(KeyValuePair<BencodeString, BencodeVariable> item)
{
if (!this.dict.ContainsKey(item.Key))
return false;
return this.dict[item.Key].Equals(item.Value);
}
public bool ContainsKey(BencodeString key)
{
foreach(KeyValuePair<BencodeString, BencodeVariable> pair in this.dict) {
if (pair.Key.Equals(key))
return true;
}
return false;
}
public void CopyTo(KeyValuePair<BencodeString, BencodeVariable>[] array, int arrayIndex) { /*...*/ }
public int Count
{
get { return this.dict.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(BencodeString key)
{
return this.dict.Remove(key);
}
public bool Remove(KeyValuePair<BencodeString, BencodeVariable> item)
{
return this.dict.Remove(item.Key);
}
public bool TryGetValue(BencodeString key, out BencodeVariable value)
{
foreach(KeyValuePair<BencodeString, BencodeVariable> pair in this.dict)
if ( pair.Key.Equals(key) ) {
value = pair.Value;
return true;
}
value = null;
return false;
}
public BencodeVariable this[BencodeString key]
{
get {
foreach(KeyValuePair<BencodeString, BencodeVariable> pair in this.dict)
if ( pair.Key.Equals(key) )
return pair.Value;
return null;
}
set { this.dict[key] = value; }
}
public ICollection<BencodeString> Keys
{
get { return this.dict.Keys; }
}
public ICollection<BencodeVariable> Values
{
get { return this.dict.Values; }
}
public IEnumerator<KeyValuePair<BencodeString, BencodeVariable>> GetEnumerator()
{
return this.dict.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.dict.GetEnumerator();
}
#endregion
}
}
class BencodeString : BencodeVariable
{
private byte[] str;
public BencodeString() {
this.str = null;
}
public BencodeString(string str) {
this.str = encoding.GetBytes(str);
}
public override bool Equals(object ob)
{
if (ob == null)
return false;
BencodeString y = ob as BencodeString;
return (encoding.GetString(this.str) == encoding.GetString(y.str));
}
public override int GetHashCode()
{
return this.str.GetHashCode();
}
}

You're relying on byte[].GetHashCode() doing something desirable. It won't. Arrays don't implement equality or hash operations - you'll get the default (identity) behaviour.
Rewrite your GetHashCode method as something like this:
public override int GetHashCode()
{
int result = 17;
foreach (byte b in str)
{
result = result * 31 + b;
}
return result;
}
(Also it's not clear what encoding is, but that's a different matter.)
Note that your Equals override will also throw a NullReferenceException if ob is a non-null reference, but not to a BencodeString.
EDIT: Assuming you're actually wanting to check for the byte arrays being the same, I wouldn't call Encoding.GetString in your equality check. There's no point. Just check the byte array contents directly. Something like this is a reasonable byte array equality check - although I'd generally prefer to write a generic equivalent:
private static bool ArraysEqual(byte[] x, byte[] y)
{
if (x == y)
{
return true;
}
if (x == null || y == null)
{
return false;
}
if (x.Length != y.Length)
{
return false;
}
for (int i = 0; i < x.Length; i++)
{
if (x[i] != y[i])
{
return false;
}
}
return true;
}
If you do want to check whether two byte arrays are decoded to equal strings, then you should use Encoding.GetString in both places... but that would rarely be an appropriate thing to do, IMO.
Mind you, it's not clear why you've got your own string-like class to start with. There are all kinds of potential problems here... unequal encodings, null references etc.

It is very important that values that are Equal also produce the same hash code. An obvious (but not necessarily efficient) workaround is this:
public override int GetHashCode()
{
return encoding.GetString(this.str).GetHashCode();
}
Making strings not behave as Unicode strings internally is a a code smell but possibly intentional here. It is normally applied at the outer interface. Your implementation would allow for the encoding to change after the string is read. But a really serious problem with that is that the dictionary is no longer valid when that happens. You won't be able to find keys back.

Related

C# operator overloading: Object.Equals(object o) & Object.GetHashCode()

So I am creating a BST and want it to be a generic tree, right now I am developing the Node<T> class. I need some help with some of the operator overloading specifics. Class is below:
public class Node<T> where T : IComparable
{
//Private member data
private T data;
private Node<T> left;
private Node<T> right;
//private readonly IComparer<T> _comparer;
//Node constructor
public Node()
{
data = default(T); //
left = null;
right = null;
}
//Setters/getters for node private data members
public T Data
{
get { return data; }
set { data = value; }
}
public Node<T> Left
{
get { return left; }
set { left = value; }
}
public Node<T> Right
{
get { return right; }
set { right = value; }
}
public static bool operator ==(Node<T> lhs, Node<T> rhs)
{
if((lhs.Data).CompareTo(rhs.Data) == 0)
{
return true;
}
else
{
return false;
}
}
public static bool operator !=(Node<T> lhs, Node<T> rhs)
{
if (lhs.Data.CompareTo(rhs.Data) != 0)
{
return true;
}
else
{
return false;
}
}
}
But Visual Studio (and sources I have seen online) say I need to overload the Object.Equals(object o) method and also the Object.GetHashCode.
From what I know about .Equals just through using C#, it's like value type semantics, or will compare the values of 2 objects, instead of their references, aka checking if they are actually the same object, which I think is what == usually does when comparing objects. So this is what I tried to do:
public override bool Equals(Object obj)
{
if ((lhs.Data).CompareTo(rhs.Data) == 0)
{
return true;
}
else
{
return false;
}
}
It's basically the same as my == operator, but it doesn't work because the lhs/rhs parameters don't exist. I have no idea how do accomplish this for my case since how I believe it will be called is n1.Equals(n2) and will check to see if the data values are the same for the nodes. Examples online are unclear to me. I also have no idea why I have to involve this hash method at all, but I am still trying to do research on that. Mostly curious about the Equals override for now.
Make sure you implement the Equals method according to the MS guide. Here is my snippet. I use all the time:
// override object.Equals
public override bool Equals(object obj)
{
// shortcut
if (object.ReferenceEquals(this, obj))
{
return true;
}
// check for null and make sure we do not break oop / inheritance
if (obj == null || GetType() != obj.GetType())
{
return false;
}
// TODO: write your implementation of Equals() here
// do not call base.equals !
throw new NotImplementedException();
return false;
}
public static bool operator ==(Class lobj, Class robj)
{
// users expect == working the same way as Equals
return object.Equals(lobj, robj);
}
public static bool operator !=(Class lobj, Class robj)
{
return !object.Equals(lobj, robj);
}
// override object.GetHashCode
public override int GetHashCode()
{
// TODO: write your implementation of GetHashCode() here
// return field.GetHashCode() ^ field2.GetHashCode() ^ base.GetHashCode();
// or simply return the unique id if any
throw new NotImplementedException();
}

How to have multiple argument's in a C# if statement

[That title may be wrong for the question, please inform me if so]
I'm coding a little maths quiz in C#, and I was wondering how to make an if statement that says something similiar to:
"if the user responds with 'this' or ' this'
{
do blahblahblah
}
But I don't know how to say the OR bit in C#, I looked through the C# operators page, but kind of got lost in the technical jargon (I'm a rookie).
This is what I have so far:
Console.WriteLine("What is 200 / 5?");
string sFirstAnswer = Console.ReadLine();
if (sFirstAnswer == "40" || " 40")
{
sUser1Score++;
Console.WriteLine("\n Correct, 200 / 5 = 40. You have been awarded 1 point.");
Console.ReadLine();
}
Write
if (sFirstAnswer == "40" || sFirstAnswer == " 40")
or better yet, trim the answer:
if (sFirstAnswer.Trim() == "40")
if (sFirstAnswer == "40" || sFirstAnswer == "40")
You can create a list of allowed answers and then check it's in the list.
var correctFirstAnswers = new List<string>{"40", " 40"};
if (correctFirstAnswers.Contains(sFirstAnswer))
this is more readable than || when there are multiple possible answers.
I thought I might give an (over-the-top) example of what I meant to make it a bit more Dynamic
A few classes now help to ask you the questions, and with a few functions built around it, you can easily show your questions in a menu format, and then ask the question, with random nr's (only whole number division was a bit more annoying :))
You could make it easier that the Generate method limits the range a bit more, but I just thought I wanted to give you an idea of how it could look like
using System;
using System.Collections.Generic;
namespace MathQuiz
{
class Program
{
interface IExercise
{
string Title { get; }
void Generate();
}
abstract class Exercise<TResult> : IExercise
{
public virtual string Title
{
get
{
return "Exercise";
}
}
public abstract bool isCorrect(TResult reply);
public abstract TResult Solve();
public abstract bool TryParse(string value, out TResult result);
public abstract void Generate();
}
abstract class ExerciseWith2Items<TSource, TResult> : Exercise<TResult>
{
public virtual TSource Item1 { get; set; }
public virtual TSource Item2 { get; set; }
public abstract string Operator { get; }
public override string ToString()
{
return string.Format("{0} {1} {2}", Item1, Operator, Item2);
}
}
abstract class WholeNumberExercise : ExerciseWith2Items<int, int>
{
public override void Generate()
{
Random next = new Random();
Item1 = next.Next(100) + 15;
Item2 = next.Next(100) + 15;
}
public override bool TryParse(string value, out int result)
{
return int.TryParse(value, out result);
}
}
class Division : WholeNumberExercise
{
protected bool IsPrime(int nr)
{
int max = (int)Math.Sqrt(nr);
if (nr <= 2)
{
return true;
}
for (int i = 2; i < max; i++)
{
if (nr % i == 0)
{
return false;
}
}
return true;
}
public override int Item1
{
get
{
return base.Item1;
}
set
{
// primes cannot be divived, so increase the value until we don't have a prime
while (IsPrime(value))
{
value++;
}
base.Item1 = value;
}
}
public override int Item2
{
get
{
return base.Item2;
}
set
{
if (value <= 0)
{
// minimum 2
value = 2;
}
// small override: we only want whole number division, so change the nr to the closest nr that has no rest after division
int closest = 0;
while ((value - closest > 1 && Item1 % (value - closest) != 0) ||
(value + closest < Item1 && Item1 % (value + closest) != 0))
{
closest++;
}
// in case closest == 0, it doesn't really change anything
if (Item1 % (value - closest) == 0)
{
value -= closest;
}
else
{
value += closest;
}
base.Item2 = value;
}
}
public override string Operator
{
get { return "/"; }
}
public override bool isCorrect(int reply)
{
return reply == (Item1 / Item2);
}
public override void Generate()
{
Random r = new Random();
Item1 = r.Next(500) + 100;
Item2 = r.Next(50) + 2;
}
public override int Solve()
{
return (Item1 / Item2);
}
}
class Multiplication : WholeNumberExercise
{
public override string Operator
{
get { return "*"; }
}
public override bool isCorrect(int reply)
{
return reply == (Item1 * Item2);
}
public override int Solve()
{
return (Item1 * Item2);
}
}
class Addition : WholeNumberExercise
{
public override string Operator
{
get { return "+"; }
}
public override bool isCorrect(int reply)
{
return reply == (Item1 + Item2);
}
public override int Solve()
{
return (Item1 + Item2);
}
}
class Subtraction : WholeNumberExercise
{
public override string Operator
{
get { return "-"; }
}
public override bool isCorrect(int reply)
{
return reply == (Item1 - Item2);
}
public override int Solve()
{
return (Item1 - Item2);
}
}
static IExercise ShowMenu(IList<IExercise> exercises)
{
int menu;
do
{
Console.Clear();
Console.WriteLine("Test your match skills :)\r\n");
for (int i = 0; i < exercises.Count; i++)
{
Console.WriteLine("\t{0}\t{1}", i, exercises[i].GetType().Name);
}
Console.WriteLine("\r\n\t99\tExit\r\n");
Console.Write("Please enter your choice: ");
if (!int.TryParse(Console.ReadLine(), out menu))
{
// wrong input
menu = -1;
}
if (menu != 99)
{
if (menu >= exercises.Count)
{
menu = -1;
}
}
} while (menu < 0);
IExercise result = null;
if (menu != 99)
{
result = exercises[menu];
}
return result;
}
static void Solve(IExercise exercise)
{
if (exercise == null)
{
return;
}
if (!(exercise is WholeNumberExercise))
{
Console.WriteLine("Don't know how to solve this exercise, please contact developer :)");
Console.ReadLine();
return;
}
var solvable = exercise as WholeNumberExercise;
solvable.Generate();
Console.Write("{0}: '{1}' = ", solvable.GetType().Name, exercise);
int reply;
bool validAnswerGiven;
do
{
validAnswerGiven = solvable.TryParse(Console.ReadLine(), out reply);
if (validAnswerGiven)
{
if (solvable.isCorrect(reply))
{
Console.WriteLine("Correct!");
}
else
{
Console.WriteLine("Incorrect, the correct result is {0}", solvable.Solve());
}
}
else
{
Console.WriteLine("Please enter valid value (whole number)!");
}
} while (!validAnswerGiven);
Console.ReadLine();
}
static void Main(string[] args)
{
IList<IExercise> potentialExercises = new List<IExercise>()
{
new Addition(),
new Subtraction(),
new Division(),
new Multiplication()
};
IExercise selectedExercise;
do
{
selectedExercise = ShowMenu(potentialExercises);
Solve(selectedExercise);
} while (selectedExercise != null);
Console.WriteLine("Program completed!");
}
}
}
it is runnable code, so copy and paste in visual studio console project should do the trick ;)
In addition to the above you could also try to convert the string to an integer
int number = 0
bool result = Int32.TryParse(Console.ReadLine(), out number);
if (number== 40){
...
}
number will be 0 if conversion fails to int and result false but for your case you dont care its not 40...
MSDN Int TryParse
Since you're validating an answer from an equation, you want to Parse it and get it into a numeric form pronto.
var answer = Convert.ToInt32(sFirstAnswer.Trim());
var expected = 40;
if(answer == expected){
//gold ribbon
}

Distinct values from List of objects

I need your help. I am trying to get distinct values from List of objects.
My class looks like this:
class Chromosome
{
public bool[][] body { get; set; }
public double fitness { get; set; }
}
Now I have List<Chromosome> population. And now what I need is a way, how I can get new list: List<Chromosome> newGeneration. This new list will contain only unique chromosomes from original list - population.Chromosome is unique, when his whole body (which in this case is 2D bool array) is unique in comparison to the other chromosomes.
I know, that there is something like MoreLINQ, but I am not sure, whether I should use 3rd party code and I know that I should overwrite some methods, but I am kind of lost. So I would really appreciate some nice step by step description, that even idiot could accomplish :)
THX
First, implement the equality operator (this goes into class Chromosome):
public class Chromosome : IEquatable<Chromosome>
{
public bool[][] body { get; set; }
public double fitness { get; set; }
bool IEquatable<Chromosome>.Equals(Chromosome other)
{
// Compare fitness
if(fitness != other.fitness) return false;
// Make sure we don't get IndexOutOfBounds on one of them
if(body.Length != other.body.Length) return false;
for(var x = 0; x < body.Length; x++)
{
// IndexOutOfBounds on inner arrays
if(body[x].Length != other.body[x].Length) return false;
for(var y = 0; y < body[x].Length; y++)
// Compare bodies
if(body[x][y] != other.body[x][y]) return false;
}
// No difference found
return true;
}
// ReSharper's suggestion for equality members
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != this.GetType())
{
return false;
}
return this.Equals((Chromosome)obj);
}
public override int GetHashCode()
{
unchecked
{
return ((this.body != null ? this.body.GetHashCode() : 0) * 397) ^ this.fitness.GetHashCode();
}
}
}
Then, use Distinct:
var newGeneration = population.Distinct().ToList();
public class ChromosomeBodyComparer : IEqualityComparer<Chromosome>
{
private bool EqualValues(bool[][] left, bool[][] right)
{
if (left.Length != right.Length)
{
return false;
}
return left.Zip(right, (x, y) => x.SequenceEquals(y)).All();
}
public bool Equals(Chromosome left, Chromosome right)
{
return EqualValues(left.body, right.body)
}
//implementing GetHashCode is hard.
// here is a rubbish implementation.
public int GetHashCode(Chromosome c)
{
int numberOfBools = c.body.SelectMany(x => x).Count();
int numberOfTrues = c.body.SelectMany(x => x).Where(b => b).Count();
return (17 * numberOfBools) + (23 * numberOfTrues);
}
}
Called by:
List<Chromosome> nextGeneration = population
.Distinct(new ChromosomeBodyComparer())
.ToList();

C# Dictionary ContainsKey

My problem is ContainsKey is always returning false even when they key has been added and .Equals evaluates to true.
I have the following class:
public class StatisticsFilter
{
private String someString1;
private String someString2;
.....
public override string ToString()
{
return string.Format("{0}-{1}-{2}-{3}-{4}", someString1, someString2, ...)
}
public override bool Equals(object obj)
{
return obj.ToString().Equals(ToString());
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
}
I then have a dictionary that looks like this:
private readonly IDictionary<StatisticsFilter, Statistics> _filteredStatisticsDict =
new Dictionary<StatisticsFilter, Statistics>();
....
{
// ALWAYS EVALUATES TO FALSE!
if (_filteredStatisticsDict.ContainsKey(statisticsFilter) == false)
{
_filteredStatisticsDict.Add(statisticsFilter, new Statistics());
}
}
Unable to reproduce with the code you've given us.
using System;
using System.Collections.Generic;
public class StatisticsFilter
{
private String someString1;
private String someString2;
public StatisticsFilter(string x, string y)
{
this.someString1 = x;
this.someString2 = y;
}
public override string ToString()
{
return string.Format("{0}-{1}xyz", someString1, someString2);
}
public override bool Equals(object obj)
{
return obj.ToString().Equals(ToString());
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
}
class Test
{
static void Main()
{
var dict = new Dictionary<StatisticsFilter, int>();
var sf1 = new StatisticsFilter("hello", "there");
var sf2 = new StatisticsFilter("hello", "there");
dict[sf1] = 10;
Console.WriteLine(dict.ContainsKey(sf2)); // Prints true
}
}
Are expecting the 'ToString()' to be the key? I think you will get the desired result by changing the Dictionary declaration to: Dictionary<string, Statistics>
// not always be false
if (_filteredStatisticsDict.ContainsKey(statistics.ToString() == false)
{
_filteredStatisticsDict.Add(statisticsFilter.ToString(), newStatisitcs());
}
If I understand what you are trying to accomplish, this should work.
With this method the dictionary key is based on the content of the filter.

c# similarity help

Anyone can explain these codes for me?
public class SimilarityImages : IComparer<SimilarityImages>, IComparable
{
private readonly ComparableImage source;
private readonly ComparableImage destination;
private readonly double similarity;
public SimilarityImages(ComparableImage source, ComparableImage destination, double similarity)
{
this.source = source;
this.destination = destination;
this.similarity = similarity;
}
public ComparableImage Source
{
get
{
return source;
}
}
public ComparableImage Destination
{
get
{
return destination;
}
}
public double Similarity
{
get
{
return Math.Round(similarity * 100, 1);
}
}
public static int operator !=(SimilarityImages value, SimilarityImages compare)
{
return value.CompareTo(compare);
}
public static int operator <(SimilarityImages value, SimilarityImages compare)
{
return value.CompareTo(compare);
}
public static int operator ==(SimilarityImages value, SimilarityImages compare)
{
return value.CompareTo(compare);
}
public static int operator >(SimilarityImages value, SimilarityImages compare)
{
return value.CompareTo(compare);
}
public override string ToString()
{
return string.Format("{0}, {1} --> {2}", source.File.Name, destination.File.Name, similarity);
}
#region IComparer<SimilarityImages> Members
public int Compare(SimilarityImages x, SimilarityImages y)
{
return x.similarity.CompareTo(y.similarity);
}
#endregion
#region IComparable Members
public int CompareTo(object obj)
{
SimilarityImages other = (SimilarityImages)obj;
return this.Compare(this, other);
}
#endregion
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
var other = (SimilarityImages)obj;
var equals = Source.File.FullName.Equals(other.Source.File.FullName, StringComparison.InvariantCultureIgnoreCase);
if (!equals)
{
return false;
}
equals = Destination.File.FullName.Equals(other.Destination.File.FullName, StringComparison.InvariantCultureIgnoreCase);
if (!equals)
{
return false;
}
return true;
}
public override int GetHashCode()
{
return string.Format("{0};{1}", Source.File.FullName, Destination.File.FullName).GetHashCode();
}
}
It looks kind of like String.Compare()
(Comparison of strings by value.)
however the return of integers for the operators <, >, <=, >=, ==, != is a bad practice - user expect a boolean return value.
Also, if the "images" are what I think they are (images as in a matrix of pixels), then returning a value for comparison is not intuitive - What comparison algorithm are you using? - Why are you providing only one comparison algorithm and hiding its name? - What if the images are not of same size or pixel format?

Categories

Resources