I have a DataTable which contains columns, some of which have a data type which is the type of a class in my project, so the column would be added to the table thus:
DataColumn column = _dataTable.Columns.Add("myColumnName", typeof(MyClass));
The problem comes when I create a DataView from the DataTable and try to set a RowFilter:
_dataView.RowFilter = "[myColumnName] = \"xyz\"";
This throws an exception "Cannot perform '=' operation on MyClass and System.String".
MyClass implements IComparable as well as Equals(object obj), ToString() and all the equality and comparison operators, but this is obviously not enough. I even tried adding a conditional branch to CompareTo(object obj) to accept an obj that is a string, but to no avail, it never even hits CompareTo.
Presumably the expression parser in DataView is simply unable to work out how to compare a MyClass to a string.
I would be grateful for any suggestions.
As requested by Cee McSharpFace, here is the relevant part of my class:
public class PartNumber : IXmlSerializable, IComparable<PartNumber>, IArithmetic, IEquatable<PartNumber>, IEquatable<string>, IComparable<string>
{
public int CompareTo(PartNumber other)
{
int result = 0;
if (other is null)
{
result = 1;
}
else
{
DoActualComparison(other);
}
return result;
}
public int CompareTo(string other)
{
return ToString().CompareTo(other);
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
public override bool Equals(object obj)
{
return !(obj is null) &&
obj is PartNumber &&
this == ((PartNumber)obj);
}
public static bool operator ==(PartNumber x, PartNumber y)
{
return x.CompareTo(y) == 0;
}
public static bool operator !=(PartNumber x, PartNumber y)
{
return !(x == y);
}
public static bool operator >(PartNumber x, PartNumber y)
{
return x.CompareTo(y) > 0;
}
public static bool operator <(PartNumber x, PartNumber y)
{
return x.CompareTo(y) < 0;
}
public bool Equals(string other)
{
return ToString().Equals(other);
}
public bool Equals(PartNumber other)
{
return Equals((object)other);
}
public static bool operator ==(PartNumber lhs, string rhs)
{
return lhs.ToString() == rhs;
}
public static bool operator !=(PartNumber lhs, string rhs)
{
return lhs.ToString() != rhs;
}
public object Add(object x)
{
return this;
}
public object Subtract(object x)
{
return this;
}
public object Multiply(object x)
{
return this;
}
public object Divide(object x)
{
return this;
}
public override string ToString()
{
return MakeObjectIntoString();
}
}
Having a column of type
PartNumbermaps to the internalStorageType.Objectin the datatable.The binary operations evaluator does not support any of its operators on this storage type:
Reference source, this is where it throws the exception you've got. The list of supported types is listed in the switch statement a few dozen lines further up.
Workaround 1:
Add a second column where you store just the
PartNumber.ToString()result, precomputed, to use in the query.To make your code compile, and for demonstration purposes, I've added a private string field for the part number, which I return in its
ToStringoverride:Usage:
--> this returns one row, as you would expect.
Workaround 2
The Convert function can deal with
StorageType.Objectand is able to convert aPartNumberinstance to a string using itsToStringproperly. So this would also work:--> I tested it, and it also returns the correct (and only) match.