C# Dictionary ContainsKey - c#

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.

Related

Simple.Mocking Expect method call with custom object

So I am using Simple.Mocking to Mock some interfaces on my tests. Some methods receive custom objects
public class MyObj
{
public int Attr { get; set; }
public override bool Equals(object obj)
{
return Equals(obj as MyObj);
}
public override int GetHashCode()
{
return Attr;
}
private bool Equals(MyObj myObj)
{
return Attr == myObj.Attr;
}
}
public interface IFoo
{
void Show(MyObj o);
}
public class ObjUnderTest
{
public ObjUnderTest(IFoo foo)
{
var o = new MyObj{ Attr = 1; };
foo.Show(o);
}
}
[TestClass]
public class TestClasse
{
[TestMethod]
public void TestShow()
{
var foo = Mock.Interface<IFoo>();
var myObj = new MyObj { Attr = 1 };
Expect.Once.MethodCall(() => foo.Show(myObj));
var objectUnderTest = new ObjUnderTest(foo);
AssertExpectations.IsMetFor(foo);
}
}
The problems is that test fails always, even when Show is called with a object with Attrequals to 1. It only pass if I write the expect like this:
Expect.Once.MethodCall(()=> foo.Show(Any<MyObj>.Value));
Which is not what I need. I know it fails because those are different objects but I have tried overriding MyObj Equals and GetHashCode with no success.
Any Ideas?
If the desired outcome is to validate the input you can try specifying exptectation with a predicate
Expect.Once.MethodCall(()=> foo.Show(Any<MyObj>.Value.Matching(obj => obj.Attr == 1)));
Source: project readme on Github - Using "wildcard" parameter values
[TestClass]
public class TestClasse {
[TestMethod]
public void TestShow() {
//Arrange
var foo = Mock.Interface<IFoo>();
Expect.Once.MethodCall(()=> foo.Show(Any<MyObj>.Value.Matching(obj => obj.Attr == 1)));
//Act
var objectUnderTest = new ObjUnderTest(foo);
//Assert
AssertExpectations.IsMetFor(foo);
}
}

c# Dictionary<object, T> lookup value

Not sure how to best phrase this which is probably why I'm having difficulty looking it up. Here is a sample console application to demonstrate my meaning.
class Program
{
static void Main(string[] args)
{
var item1 = new Item("Number");
var item2 = new Item("Number");
var dict = new Dictionary<Item, string>();
dict.Add(item1, "Value");
Console.WriteLine(dict.ContainsKey(item2));
var dict2 = new Dictionary<string, string>();
dict2.Add("Number", "Value");
Console.WriteLine(dict2.ContainsKey("Number"));
Console.Read();
}
class Item
{
readonly string number;
public Item(string number)
{
this.number = number;
}
}
}
In this example dict.ContainsKey(item2) returns false and dict2.ContainsKey("Number") returns true. Can Item be defined in such a way that it would behave like a string? The best I can come up with is
static void Main(string[] args)
{
var item1 = new Item("Number");
var item2 = new Item("Number");
var dict = new Dictionary<string, string>();
dict.Add(item1.ToString(), "Test");
Console.WriteLine(dict.ContainsKey(item2.ToString()));
Console.Read();
}
class Item
{
readonly string number;
public Item(string number)
{
this.number = number;
}
public override string ToString()
{
return number;
}
}
This example is contrived, Item would have more fields and ToString() would joint them all up.
You need to override Equals and GetHashCode. Dictionary use Equals and GetHashCode method to compare keys for equality.
class Item
{
readonly string number;
public Item(string number)
{
this.number = number;
}
public override bool Equals(object obj)
{
return Equals(obj as Item);
}
public override int GetHashCode()
{
// this is c# 6 feature
return number?.GetHashCode() ?? 0;
// If you are not using c# 6, you can use
// return number == null ? 0 : number.GetHashCode();
}
private bool Equals(Item another)
{
if (another == null)
return false;
return number == another.number;
}
}
If you have more than one field, you need to account all fields in the Equals and GetHashCode method.

Filtering unique data with Column combinations in C#

I have a list as following:
public class MyClass
{
public int val1;
public long val2;
public string val3;
}
class Program
{
static void Main(string[] args)
{
List<MyClass> lstData=new List<MyClass>
{
new MyClass{val1=1,val2=2,val3="AA"},
new MyClass{val1=1,val2=2,val3="BB"},
new MyClass{val1=3,val2=4,val3="AA"},
new MyClass{val1=3,val2=4,val3="BB"},
new MyClass{val1=1,val2=2,val3="BB"},
new MyClass{val1=3,val2=4,val3="AA"},
};
}
}
I want to get unique rows out of the list.In the above example following lists are duplicate
{val1=1,val2=2,val3="BB"}
{val1=3,val2=4,val3="AA"}
I want to eliminate the duplicate rows and get the distinct rows out of the list.
How I can do that?
var result = lstData.GroupBy(x=>new {x.val1, x.val2, x.val3}, (x,y)=>y.First())
.ToList();
Assuming that your real class MyClass overrides Equals and GetHashCode, all you need is to add Distinct:
lstData = lstData.Distinct().ToList();
You have to either implement GetHashCode and Equals methods on your MyClass class, or define custom class which implements IEqualityComparer<MyClass>.
public class MyClassEqualityComparer : IEqualityComparer<MyClass>
{
private static Lazy<MyClassEqualityComparer> _instance = new Lazy<MyClassEqualityComparer>(() => new MyClassEqualityComparer());
public static MyClassEqualityComparer Instance
{
get { return _instance.Value; }
}
private MyClassEqualityComparer() { }
public bool Equals(MyClass x, MyClass y)
{
return x.val1 == y.val1 && x.val2 == y.val2 && x.val3 == y.val3;
}
public int GetHashCode(MyClass obj)
{
return obj.val1.GetHashCode() ^ obj.val2.GetHashCode() ^ obj.val3.GetHashCode();
}
}
With that you'll be able to use LINQ Distinct() method:
var distinct = lstData.Distinct(MyClassEqualityComparer.Instance).ToList();

C#, Updating a List using a delegate function as a filter

I want to update a list of objects(mycapsule, has many other members) when a condition (pred) holds for one of its class members(value). Whenever I change something another thing fails, I'm newbie in C# and really confused.
Can somebody fix my code:
In the best condition I only get get this error but I think many things are missing in my code
The type or namespace name `T' could not be found. Are you missing a using directive or an assembly reference?
here is my code
using System;
using System.Collections.Generic ;
namespace test
{
class MainClass
{
public static List< mycapsule<int,double> > sample= new List< mycapsule<int,double>>();
public static void Main (string[] args)
{
sample.Add(new mycapsule<int,double> {id=1 , value= 1.2});
update(pred, 12.3);
}
public static bool pred(double x)
{
if (x==2.5) return true;
return false;
}
public class mycapsule<KT, T>
{
public KT id {get ; set; }
public T value { get ; set; }
public int p; // and more
}
public bool update(Func<T, bool> predicate, T i)
{
foreach (var x in sample.FindAll(item => predicate(JustValue(item))) )
{
x.value = i ;
}
return true ;
}
public T JustValue(mycapsule<int,T> i)
{
return i.value;
}
}
}
Look at your update method:
public bool update(Func<T, bool> predicate, T i)
{
foreach (var x in KeyRecord.FindAll(item => predicate(JustValue(item))) )
{
x.value = i ;
}
return true ;
}
What do you expect T to be here? The method is not generic (it's not written as update<T>) and it's not declared in a generic class.
It's possible that you just want:
public bool update<T>(Func<T, bool> predicate, T i)
... but it's hard to say without knowing what KeyRecord.FindAll looks like. Oh, and you've got the same problem with JustValue.
As a side issue, the method names update and pred don't follow .NET naming conventions, and JustValue is a poor method name in terms of descriptiveness. mycapsule also doesn't follow .NET naming conventions. These things really matter in terms of readability.
I'm afraid this won't work due to type safety reasons. I corrected the code as much as possible and got this:
public static List<mycapsule<int, double>> sample = new List<mycapsule<int, double>>();
public static void Main(string[] args)
{
sample.Add(new mycapsule<int, double> { id = 1, value = 1.2 });
update(pred, 12.3);
}
public static bool pred(double x)
{
if (x == 2.5) return true;
return false;
}
public class mycapsule<KT, T>
{
public KT id { get; set; }
public T value { get; set; }
public int p; // and more
}
public static bool update<T>(Func<T, bool> predicate, T i)
{
List<mycapsule<int, double>> list = sample.FindAll(item => predicate(JustValue(item)));
foreach (var x in list)
{
x.value = i;
}
return true;
}
public static T JustValue<T>(mycapsule<int, T> i)
{
return i.value;
}
The error is:
predicate(JustValue(item)) => Argument 1: cannot implicitly convert from double to T
This comes from the fact that you are trying to forcefully call a method that you've specified as taking a generic type T (Func<T, bool>) with a value that is known to be double. Although we know that T will be double from the call to update(pred, 12.3);, nothing prevents me from passing in a predicate that takes an incompatible type e.g.:
public static bool pred(string x)
{
return false;
}
and
update(pred, "asdf");
Which is clearly inconsistent. The compiler is simply trying to prevent you from shooting yourself in the foot accidentally.
To solve this, you could explicitly pass the collection to the update method, thus ensuring that the types are consistent:
public static List<mycapsule<int, double>> sample = new List<mycapsule<int, double>>();
public static void Main(string[] args)
{
sample.Add(new mycapsule<int, double> { id = 1, value = 1.2 });
update(pred, 12.5, sample);
}
public static bool pred(double x)
{
if (x == 2.5) return true;
return false;
}
public class mycapsule<KT, T>
{
public KT id { get; set; }
public T value { get; set; }
public int p; // and more
}
public static bool update<T>(Func<T, bool> predicate, T i, List<mycapsule<int, T>> list)
{
foreach (var x in list.FindAll(item => predicate(JustValue(item))))
{
x.value = i;
}
return true;
}
public static T JustValue<T>(mycapsule<int, T> i)
{
return i.value;
}
Try this, And for generic method the method definition you have used is not correct.
It should be
//MethodName<T,U>(T para1, U para2)
I have change the code to include reflections, this should work.
Please try and give feedback.
using System;
using System.Collections.Generic;
using System.Reflection;
namespace test
{
class MainClass
{
public static List<Mycapsule<int, double>> sample = new List<Mycapsule<int, double>>();
public static void Main(string[] args)
{
sample.Add(new Mycapsule<int, double> { id = 1, value = 1.2 });
update(pred, 12.3);
}
public static bool pred(double x)
{
if (x == 2.5) return true;
return false;
}
public static bool update<T>(Func<T, bool> predicate, T i)
{
var myCollection = sample.FindAll(p => pred(JustValue<double>(p)));
MainClass mainClass = new MainClass();
foreach (var x in myCollection)
{
MethodInfo changeTypeMethod = typeof(MainClass).GetMethod("GetValue");
object value = changeTypeMethod.Invoke(mainClass, new object[] { i, typeof(T) });
PropertyInfo valueProperty = x.GetType().GetProperty("value");
valueProperty.SetValue(x, value);
}
return true;
}
public T GetValue<T>(T i)
{
return (T)Convert.ChangeType(i, typeof(T));
}
public static T JustValue<T>(Mycapsule<int, T> i)
{
return i.value;
}
}
//Outside the MainClass inside the same namespace
public class Mycapsule<KT, T>
{
public KT id { get; set; }
public T value { get; set; }
public int p; // and more
}
}

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

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.

Categories

Resources