C# How to call overloaded operator in generic parent class? - c#

Following problem:
In the definition of an function of a generic parent class ParentA I want to call an overloaded operator from ChildB:
See the following structure
class ParentA<T> where T : ParentB
{
public bool Contains(T element)
{
T element2;
return element==element2;
}
}
class ChildB : ParentB
{
public static bool operator ==(ChildB s1, ChildB s2)
{
//this one should be used
}
}
ChildA :ParentA<ChildB>
{
//make use of inherited function Contains(ChildB element)
}
I want to call the overloaded == operator of ChildB, but instead when I call the Contains function in ChildA the original ==operator from ParentB will be called.
Any idea how to make this work?
The Original code is a bit more nasty
public abstract class ElementBase
{
protected Element element;
public Element Element
{
get { return element; }
set { element = value; }
}
public static bool operator ==(ElementBase e1, ElementBase e2)
{
return e1.element == e2.element;
}
public static bool operator !=(ElementBase e1, ElementBase e2)
{
return e1.element != e2.element;
}
public override bool Equals(object obj)
{
if ((obj == null) || !this.GetType().Equals(obj.GetType()))
return false;
else
{
ElementBase element = (ElementBase)obj;
return this == element;
}
}
}
public class Structure : ElementBase
{
public bool flag;
public static bool operator ==(Structure s1, Structure s2)
{
return s1.element == s2.element && s1.flag==s2.flag;
}
public static bool operator !=(Structure s1, Structure s2)
{
return s1.element != s2.element || s1.flag!=s2.flag;
}
public override bool Equals(object obj)
{
if ((obj == null) || !this.GetType().Equals(obj.GetType()))
return false;
else
{
Structure structure = (Structure)obj;
return this == structure;
}
}
}
public class MapBase<T> where T : ElementBase
{
protected Dictionary<long, T> elements = new Dictionary<long, T>();
public bool Contains(T element)
{
...
return element==elements[id];
}
}
public class StructureMap : MapBase<Structure>
{
void someFunction()
{
//make use of Contains(Structure element)
}
}
Update
I replaced
return element==element2;
by
return element.Equals(element2);
and now it seems like it does the trick. I just don't understand why...

Related

Possible null reference in IEquatable implementation

I'm trying to find out how to remove that possible null reference in the IEquatable implementation below.
return other != null && _guid == other._guid; Possible null reference argument for parameter 'left' in 'bool SubscriptionToken.operator !=(SubscriptionToken left, SubscriptionToken right)'
public class SubscriptionToken : IEquatable<SubscriptionToken>
{
public static readonly SubscriptionToken Empty = new(Guid.Empty);
private readonly Guid _guid;
private SubscriptionToken(Guid guid)
{
_guid = guid;
}
private SubscriptionToken()
{
}
public Guid Value => _guid;
public bool Equals(SubscriptionToken? other)
{
return other != null && _guid == other._guid; // Possible null reference
}
public bool IsValid()
{
return _guid != Guid.Empty;
}
public static SubscriptionToken New()
{
return new SubscriptionToken(Guid.NewGuid());
}
public override bool Equals(object? other)
{
return other is SubscriptionToken token && Equals(token);
}
public override int GetHashCode()
{
return HashCode.Combine(_guid);
}
public override string ToString()
{
return _guid.ToString("N");
}
public static bool operator ==(SubscriptionToken left, SubscriptionToken right)
{
return EqualityComparer<SubscriptionToken>.Default.Equals(left, right);
}
public static bool operator !=(SubscriptionToken left, SubscriptionToken right)
{
return !(left == right);
}
}
Your equals method should probably look something like this:
public bool Equals(SubscriptionToken other)
{
if (ReferenceEquals(null, other)) return false;
return _guid.Equals(other._guid);
}
That should avoid any null reference exceptions.

How to enforce class types when comparing their int id properties

I have several classes with id property of the same type int?:
public class Person {
public int? id { get; set; }
}
public class Project {
public int? id { get; set; }
}
// etc...
When writing code it happened that I compared semantically wrong types:
if (person.id == project.id), and of course there was no warning until I found the bug.
How could I create some kind of underlying type enforcement, or even better, a compiler warning, or something like that, that warns me not everything looks o.k.?
I can think of creating an Equals(Person p) { return p.id == this.id } but I'd prefer some other mechanism that could be used more 'freely'.
You need to override Equals and GetHashCode to be able to compare objects directly.
Try like this:
public sealed class Person : IEquatable<Person>
{
private readonly int? _id;
public int? Id { get { return _id; } }
public Person(int? id)
{
_id = id;
}
public override bool Equals(object obj)
{
if (obj is Person)
return Equals((Person)obj);
return false;
}
public bool Equals(Person obj)
{
if (obj == null) return false;
if (!EqualityComparer<int?>.Default.Equals(_id, obj._id)) return false;
return true;
}
public override int GetHashCode()
{
int hash = 0;
hash ^= EqualityComparer<int?>.Default.GetHashCode(_id);
return hash;
}
public override string ToString()
{
return String.Format("{{ Id = {0} }}", _id);
}
public static bool operator ==(Person left, Person right)
{
if (object.ReferenceEquals(left, null))
{
return object.ReferenceEquals(right, null);
}
return left.Equals(right);
}
public static bool operator !=(Person left, Person right)
{
return !(left == right);
}
}
public sealed class Project : IEquatable<Project>
{
private readonly int? _id;
public int? Id { get { return _id; } }
public Project(int? id)
{
_id = id;
}
public override bool Equals(object obj)
{
if (obj is Project)
return Equals((Project)obj);
return false;
}
public bool Equals(Project obj)
{
if (obj == null) return false;
if (!EqualityComparer<int?>.Default.Equals(_id, obj._id)) return false;
return true;
}
public override int GetHashCode()
{
int hash = 0;
hash ^= EqualityComparer<int?>.Default.GetHashCode(_id);
return hash;
}
public override string ToString()
{
return String.Format("{{ Id = {0} }}", _id);
}
public static bool operator ==(Project left, Project right)
{
if (object.ReferenceEquals(left, null))
{
return object.ReferenceEquals(right, null);
}
return left.Equals(right);
}
public static bool operator !=(Project left, Project right)
{
return !(left == right);
}
}
I also implemented IEquatable<Person> and == and != for good measure.
Now you can write person1 == this if this is a Person, but you would have a compiler error if this were a Project.
This is what tests are for. This is why you should write tests. Tests should pick up on these kind of errors.
But if you really want to go overkill, create a custom struct to store your IDs:
public struct Id<T> {
public int? ID { get; }
public static implicit operator Id<T>(int id) {
return new Id<T>(id);
}
public Id(int? id) { ID = id; }
public static bool operator ==(Id<T> lhs, Id<T> rhs) {
return lhs.ID == rhs.ID;
}
public static bool operator !=(Id<T> lhs, Id<T> rhs) {
return lhs.ID != rhs.ID;
}
}
// usage:
public class Person {
public Id<Person> Id { get; set; }
}
public class Project {
public Id<Project> Id { get; set; }
}
Whenever you try to compare Person.Id with Project.Id, the compiler will give you an error because you are comparing Id<Project> and Id<Person>.

Abstract class to implement equality operators

Lets say I define the following abstract class:
public abstract class ValueEquality<T> : IEquatable<T>
where T : ValueEquality<T>
{
public override bool Equals(object obj)
{
return Equals(obj as T);
}
public static bool operator ==(ValueEquality<T> lhs, object rhs)
{
if (ReferenceEquals(lhs, rhs))
{
return true;
}
else if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))
{
return false;
}
else
{
return lhs.Equals(rhs);
}
}
public static bool operator !=(ValueEquality<T> lhs, object rhs)
{
return !(lhs == rhs);
}
public bool Equals(T other)
{
return other != null && EqualNoNull(other);
}
public abstract override int GetHashCode();
public abstract bool EqualNoNull(T other);
}
And then create a class C as follows:
public class C : MyEquatable<C>
{
public override bool EqualsNoNull(C other)
{
...
}
public override int GetHashCode()
{
...
}
}
If I then have the code:
C x1;
C x2;
bool equal = x1 == x2;
Will this end up calling the equals method in C? Are there any gotchas with this approach?
Edit: fixed some issues in code raised by answers.
This code will do infinite loop in:
public override bool Equals(object obj)
{
try
{
T otherT = (T) obj;
return Equals(this, otherT);
}
catch (InvalidCastException)
{
return false;
}
}
It will call Equals(object obj) again and again. Right implementation:
public abstract class MyEquatable<T> : IEquatable<T>
where T : MyEquatable<T>
{
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((MyEquatable<T>)obj);
}
protected bool Equals(MyEquatable<T> other)
{
return this.Equals(other as T);
}
public static bool operator ==(MyEquatable<T> lhs, object rhs)
{
return Equals(lhs, rhs);
}
public static bool operator !=(MyEquatable<T> lhs, object rhs)
{
return Equals(lhs, rhs);
}
public abstract bool Equals(T other);
public abstract override int GetHashCode();
}
x1 == x2 will call operator == of MyEquatable, that will call Equals(object obj). Finally, it calls Equals(T other) overridden in C class
Another implementation which follows what is usually advised in documentation
public abstract class MyEquatable<T> : IEquatable<T>
where T : MyEquatable<T> {
public override bool Equals(object obj) {
if (ReferenceEquals(obj, null) || obj.GetType() != GetType())
return false;
var valueObject = obj as T; //Note the cast
if (ReferenceEquals(valueObject, null))
return false;
return Equals(valueObject); //Calls Equals(T other)
}
public abstract bool Equals(T other);
public abstract override int GetHashCode();
public static bool operator ==(MyEquatable<T> left, MyEquatable<T> right) {
if (ReferenceEquals(left, null) && ReferenceEquals(right, null))
return true;
if (ReferenceEquals(left, null) || ReferenceEquals(right, null))
return false;
return left.Equals(right);
}
public static bool operator !=(MyEquatable<T> left, MyEquatable<T> right) {
return !(left == right);
}
}

set multiple return value for method declaration

I have a function as below:
public var UpdateMapFetcher(int stationID, int typeID)
I need this function to return either string or int.
My return value is set as below
if (finaloutput == "System.String")
{
// param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string));
returnvalue = returnvalue.ToString();
return returnvalue;
}
else if (finaloutput == "System.Int32")
{
int a=0;
a = Convert.ToInt32(returnvalue);
return a;
}
How to have either one data type as return value in dynamic environment.
My intuition tells me, that you are trying to convert string value to some type. In that case you can use:
public T UpdateMapFetcher<T>(int stationID)
{
//var someValue = "23";
return (T)Convert.ChangeType(someValue, typeof(T));
}
//then
var typed = UpdateMapFetcher<int>(6);
In case you don't know T, you can use mapping (0-int, 1-string, etc.):
public object UpdateMapFetcher(int stationID, int type)
{
var typeMap = new []{ typeof(int), typeof(string)};
//var someValue = "23";
return Convert.ChangeType(someValue, typeMap[type]);
}
//then
var untyped = UpdateMapFetcher(6, 0/*0 is int*/);
if (untyped.GetType() == typeof(int))
{ /*is int*/
}
Another solution is to use implicit conversions:
public class StringOrInt
{
private object value;
public ValueType Type { get; set; }
public static implicit operator StringOrInt(string value)
{
return new StringOrInt()
{
value = value,
Type = ValueType.String
};
}
public static implicit operator StringOrInt(int value)
{
return new StringOrInt()
{
value = value,
Type = ValueType.Int
};
}
public static implicit operator int(StringOrInt obj)
{
return (int)obj.value;
}
public static implicit operator string(StringOrInt obj)
{
return (string)obj.value;
}
}
public enum ValueType
{
String,
Int
}
And then (simplified):
public static StringOrInt UpdateMapFetcher(int stationID, int typeID)
{
if (typeID == 0)
return "Text";
return 23;
}
private static void Main(string[] args)
{
var result = UpdateMapFetcher(1, 1);
if (result.Type == ValueType.String) { }//can check before
int integer = result;//compiles, valid
string text = result;//compiles, fail at runtime, invalid cast
}
you can return an object. You'd have to subsequently check for types in your consuming method. I assume that won't be a problem in your usecase.
your method signature is therefore:
public object UpdateMapFetcher(int stationID, int typeID)
You also have the option of using the out keyword, which permits you to accept both into variables and check after the function has been called.
public void UpdateMapFetcher(int stationID, int typeID, out int intValue, out string strValue)
// or int return val and out string value
public int UpdateMapFetcher(int stationID, int typeID, out string strValue)
With the use appearing something like this:
int intVal;
string strVal;
UpdateMapFetcher(stationID, typeID, out intVal, out strVal);
if (strVal != null)
{
doSomethingWithString(strVal);
}
else
{
doSomethingWithInt(intVal);
}
Frankly, I would just return a Tuple, with string being non-null indicating string value to use, and null as indicator for int return
public Tuple<string, int> UpdateMapFetcher(int stationID, int typeID) {
if (finaloutput == "System.String")
{
// param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string));
returnvalue = returnvalue.ToString();
return new Tuple<string, int>(returnvalue, 0);
}
else if (finaloutput == "System.Int32")
{
int a=0;
a = Convert.ToInt32(returnvalue);
return new Tuple<string, int>(null, a);
}
}
On consumer side
var rc = UpdateMapFetcher( .... );
if (rc.Item1 != null) {
// code to use string value
} else {
// code to use int value
}
I would choose to return an object of new class which might look like this:
class Result {
public string StringValue { get; }
public string Int32Value { get; }
public bool IsString { get; }
public bool IsInt32 { get; }
public Result(string value) {
StringValue = value;
IsString = true;
}
public Result(int value) {
Int32Value = value;
IsInt32 = true;
}
}
This way you can check which Type is it by using Isxxx property. You can also enhance this with validation in value geters. F. e., for string it might look like this:
public string StringValue {
get {
if (IsString)
return m_stringValue;
throw new InvalidOperationException("Value is not a string.");
}
}
You can't really do exactly that, but there are several ways to do more or less what you want. You'd probably be better off change the design a little though.
Two ideas:
Either change your code to use two different methods, and call each of them as needed instead.
..Or return an object, which you can cast however you like..
..Or, use a generic method with TypeDescriptor, like the following.
Note that we here convert the value to string first even if it was an int, since we can then use a common method ConvertFromString() to convert it to whatever type T was.
public T UpdateMapFetcher<T>(int stationID, int typeID) {
// To allow parsing to the generic type T:
var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
if(converter != null)
{
return (T)converter.ConvertFromString(returnvalue.ToString());
}
else
{
return default(T);
}
}
Usage:
var result = MyExtensions.UpdateMapFetcher<string>(1, 2);
or:
var result = MyExtensions.UpdateMapFetcher<int>(1, 2);
You can return Object and cast to type which you want.
public Object UpdateMapFetcher(int stationID, int typeID)
if (finaloutput == "System.String")
{
// param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string));
returnvalue = returnvalue.ToString();
return returnvalue;
}
else if (finaloutput == "System.Int32")
{
int a=0;
a = Convert.ToInt32(returnvalue);
return a;
}
A type that can contain either one type or another is usually called (unsurprisingly) Either. It is a special case of a sum type, basically a discriminated union, tagged union, or disjoint union with exactly two cases (instead of an arbitrary number).
Unfortunately, there does not exist an implementation of an Either type in the standard libraries, but there are plenty of implementations to be found on Google, GitHub, and elsewhere … and porting one of the existing implementations from e.g. Haskell or Scala isn't that hard, either.
It looks a bit like this (forgive my code, I don't actually know C♯ that well):
using System;
abstract class Either<A, B>
{
public abstract bool IsLeft { get; }
public abstract bool IsRight { get; }
public abstract A Left { get; }
public abstract B Right { get; }
public abstract A LeftOrDefault { get; }
public abstract B RightOrDefault { get; }
public abstract void ForEach(Action<A> action);
public abstract void ForEach(Action<B> action);
public abstract void ForEach(Action<A> leftAction, Action<B> rightAction);
private sealed class L : Either<A, B>
{
private A Value { get; }
public override bool IsLeft => true;
public override bool IsRight => false;
public override A Left => Value;
public override B Right { get { throw new InvalidOperationException(); } }
public override A LeftOrDefault => Value;
public override B RightOrDefault => default(B);
public override void ForEach(Action<A> action) => action(Value);
public override void ForEach(Action<B> action) {}
public override void ForEach(Action<A> leftAction, Action<B> rightAction) => leftAction(Value);
internal L(A value) { Value = value; }
}
private sealed class R : Either<A, B>
{
private B Value { get; }
public override bool IsLeft => false;
public override bool IsRight => true;
public override A Left { get { throw new InvalidOperationException(); } }
public override B Right => Value;
public override A LeftOrDefault => default(A);
public override B RightOrDefault => Value;
public override void ForEach(Action<A> action) {}
public override void ForEach(Action<B> action) => action(Value);
public override void ForEach(Action<A> leftAction, Action<B> rightAction) => rightAction(Value);
internal R(B value) { Value = value; }
}
public static Either<A, B> MakeLeft(A value) => new L(value);
public static Either<A, B> MakeRight(B value) => new R(value);
}
And you'd use it like this:
static class Program
{
public static void Main()
{
var input = Console.ReadLine();
int intResult;
var result = int.TryParse(input, out intResult) ? Either<int, string>.MakeLeft(intResult) : Either<int, string>.MakeRight(input);
result.ForEach(r => Console.WriteLine("You passed me the integer one less than " + ++r), r => Console.WriteLine(r));
}
}

Best practices for common logic on classes

I have a big big class, around 4000 thousands lines, and I think it can be another way to do the following.
It is a class for serialize a message, the nested classes are always with the same structure and overrides the ToString and Equal methods. There are simple classes like the following and complex classes which implements those simples classes in properties.
My idea is something like an extension class who implements the override and extend the simples classes with it
Example class
[Serializable]
[XmlType(AnonymousType = true)]
[XmlRoot(Namespace = "", IsNullable = false)]
public class ID
{
#region Public Properties
[XmlAttribute("ID")]
public String Value { get; set; }
#endregion
#region Public Methods and Operators
public static bool operator == (ID left, ID right)
{
return Equals(left, right);
}
public static bool operator != (ID left, ID right)
{
return !Equals(left, right);
}
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 Equals((ID) obj);
}
public override int GetHashCode ()
{
return (Value != null
? Value.GetHashCode()
: 0);
}
public override String ToString ()
{
return Value;
}
#endregion
#region Methods
protected bool Equals (ID other)
{
return string.Equals(Value, other.Value);
}
#endregion
}
My idea
public class FieldExtension
{
public String Value { get; set; }
#region Public Methods and Operators
public static bool operator == (FieldExtension left, FieldExtension right)
{
return Equals(left, right);
}
public static bool operator != (FieldExtension left, FieldExtension right)
{
return !Equals(left, right);
}
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 Equals((ID) obj);
}
public override int GetHashCode ()
{
return (Value != null
? Value.GetHashCode()
: 0);
}
public override String ToString ()
{
return Value;
}
#endregion
#region Methods
protected bool Equals (ID other)
{
return string.Equals(Value, other.Value);
}
#endregion
}
public class ID: FieldExtension
{
#region Public Properties
[XmlAttribute("ID")]
public String Value { get; set; }
#endregion
}
I don't know if this is possible and I just ask if some did that before or something like that or another ideas, if works will save me a lot of work
Thanks in advance
EDIT
Example complex class
[Serializable]
[XmlType(AnonymousType = true)]
[XmlRoot(Namespace = "", IsNullable = false)]
public class Zählpunkt
{
#region Public Properties
[XmlElement("ID")]
public ID ID { get; set; }
[XmlAttribute("Zählpunkt")]
public String Value { get; set; }
#endregion
..
You would make the base class FieldExtension abstract, and the Value property abstract:
public abstract class FieldExtension
{
public abstract String Value { get; set; }
...
Then in the ID class you override the property:
override public String Value { get; set; }
That makes the code in the base class use the value that you implement in the class that inherits it.

Categories

Resources