Best practices for common logic on classes - c#

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.

Related

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>.

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

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...

Distinct Certain Key Object

i have this certain Key in my Dictionary:
public class KKey
{
public string Name { get; set; }
public Guid Guid { get; set; }
}
Dictionary<KKey, string> myDictionary = new Dictionary<KKey, string>();
problem was everytime I generate new Guid, this condition wouldnt work:
if (false == myDictionary.TryGetValue(key, out keyobj))
because Guid key was new ...
Now my question was, how can i make condition that verify if Kkey.Name was already added, then dont add?
You either need to create a custom comparer or have your class override Equals and GetHashCode
Option 1: Comparer
sealed class NameEqualityComparer : IEqualityComparer<KKey>
{
public bool Equals(KKey x, KKey y)
{
return string.Equals(x.Name, y.Name);
}
public int GetHashCode(KKey obj)
{
return (obj.Name != null ? obj.Name.GetHashCode() : 0);
}
}
Dictionary<KKey, string> myDictionary = new Dictionary<KKey, string>(new NameEqualityComparer());
Option 2: Override
public class KKey : IEquatable<KKey>
{
public string Name { get; set; }
public Guid Guid { get; set; }
public bool Equals(KKey other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return string.Equals(Name, other.Name);
}
public override bool Equals(object obj)
{
return Equals(obj as KKey);
}
public override int GetHashCode()
{
return (Name != null ? Name.GetHashCode() : 0);
}
}
Dictionary<KKey, string> myDictionary = new Dictionary<KKey, string>();
can also be
bool alreadyAdded = keywordList.Any(n => n.Key.Name == name);
if (!alreadyAdded) { }

How do I map a table were primary key and identifier is not the same column?

I have to access a legacy database in which I'm faced with the following:
A column 'unit_name' is defined as primary key and is a string, and another column 'id' is defined as a classic int identifier.
My question is - how do I map this correct in Fluent NHibernate?
Currently my mapping looks like this, but I can't find any proper documentation for my scenario, so I'm not sure if it is correct.
public InputMap()
{
Table("input");
Map(x => x.unit_name).Not.Nullable().Unique();
//other mappings ...
Id(x => x.id).Column("id").Not.Nullable();
//Maybe use this instead? NaturalId().Property(x => x.unit_name);
}
Full context:
In my hunt for documentation I've created an id class that implements Equals and GetHashCode, but that might be overkill after all.
[Serializable]
public class GenericEntityId : EntityId, IEquatable<GenericEntityId>
{
public GenericEntityId(string idString)
{
IdString = idString;
}
public string IdString { get; set; }
private Guid _internalId { get; set; }
protected GenericInoEntityId()
{
_internalId = Guid.NewGuid();
}
public virtual bool Equals(GenericEntityId obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (GetType() != obj.GetType()) return false;
if (!string.IsNullOrEmpty(IdString) )
return obj.IdString == IdString;
return false;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (GetType() != obj.GetType()) return false;
return Equals((GenericEntityId)obj);
}
public override int GetHashCode()
{
if (!string.IsNullOrEmpty(IdString))
{
return (IdString.GetHashCode() * 397) ^ GetType().GetHashCode();
}
else
{
return (_internalId.GetHashCode() * 397) ^ GetType().GetHashCode();
}
}
public static bool operator ==(GenericEntityId left, GenericEntityId right)
{
return Equals(left, right);
}
public static bool operator !=(GenericEntityId left, GenericEntityId right)
{
return !Equals(left, right);
}
}
and EntityId is just an abstract class:
public abstract class EntityId
{
public abstract override int GetHashCode();
}
The reason for creating an abstract base is that I want to have a generic base I can use for all my repositories no matter if they have a string primary key or a composite key (or maybe the identifier)
[Serializable]
public abstract class EntityBase
{
public abstract EntityId entityId { get; }
protected EntityBase()
{
}
}
public class GenericRepository<TEntity> : SessionManagerBase, IEntityRepository<TEntity> where TEntity : EntityBase
{
public TEntity GetById(EntityId id)
{
ISession currentSession = OpenSession;
var returnObject = currentSession.Get<TEntity>(id);
return returnObject;
}
}
This is Nhibernate mapping-by-code, but fluent should be similar
domain object class
public class TestEntity
{
public String unit_name { get; set; }
public Int32 id { get; protected set; }
}
mapping class
public class TestEntityMap : ClassMapping<TestEntity>
{
public TestEntityMap()
{
Id( x => x.unit_name, map =>
{
map.Column("user_name");
map.Generator(Generators.Assigned);
});
Property(x => x.id, map =>
{
map.Generated(PropertyGeneration.Always);
map.Unique(true);
map.NotNullable(true);
});
}
}

How do I implement equality for an abstract base class?

I'm following the MSDN guidance for value equality, and I found a case that the documentation didn't cover, equality for a base class.
A little background:
I'm working on a Mahjong game (4-player, not matching), and I'm working on defining the tiles. Tiles can be broken into two groups: suits, which have a number associated with them (and can be put together in sequences, like 2-3-4) and honor tiles, which have no number.
Here's what I have so far:
public enum MahjongSuitType
{
Bamboo = 1,
Character,
Dot
}
public enum MahjongSuitNumber
{
One = 1,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine
}
public enum MahjongHonorType
{
GreenDragon = 1,
RedDragon,
WhiteDragon,
EastWind,
SouthWind,
WestWind,
NorthWind
}
public abstract class MahjongTile
{
}
public class MahjongSuitTile : MahjongTile, IEquatable<MahjongTile>
{
public MahjongSuitType SuitType { get; private set; }
public MahjongSuitNumber SuitNumber { get; private set; }
public bool IsRedBonus { get; private set; } //this has no bearing on equality
public MahjongSuitTile(MahjongSuitType suitType,
MahjongSuitNumber suitNumber,
bool isRedBonus = false)
{
this.SuitType = suitType;
this.SuitNumber = suitNumber;
this.IsRedBonus = isRedBonus;
}
public override bool Equals(object obj)
{
return this.Equals(obj as MahjongTile);
}
public bool Equals(MahjongTile other)
{
if (Object.ReferenceEquals(other, null))
return false;
if (Object.ReferenceEquals(other, this))
return true;
MahjongSuitTile otherSuitTile = other as MahjongSuitTile;
if (Object.ReferenceEquals(otherSuitTile, null))
return false;
return (this.SuitType == otherSuitTile.SuitType) &&
(this.SuitNumber == otherSuitTile.SuitNumber);
}
public override int GetHashCode()
{
return this.SuitType.GetHashCode() ^ this.SuitNumber.GetHashCode();
}
}
public class MahjongHonorTile : MahjongTile, IEquatable<MahjongTile>
{
public MahjongHonorType HonorType { get; private set; }
public MahjongHonorTile(MahjongHonorType honorType)
{
this.HonorType = HonorType;
}
public override bool Equals(object obj)
{
return this.Equals(obj as MahjongTile);
}
public bool Equals(MahjongTile other)
{
if (Object.ReferenceEquals(other, null))
return false;
if (Object.ReferenceEquals(other, this))
return true;
MahjongHonorTile otherHonorTile = other as MahjongHonorTile;
if (Object.ReferenceEquals(otherHonorTile, null))
return false;
return this.HonorType == otherHonorTile.HonorType;
}
public override int GetHashCode()
{
return this.HonorType.GetHashCode();
}
}
For the majority of the code, I'd like to refer to the tiles via the base class, something like:
List<MahjongTile> hand = new List<MahjongTile>() { ... };
HashSet<MahjongTile> dragonTiles = new HashSet()
{
new MahjongHonorTile(MahjongHonorType.GreenDragon),
new MahjongHonorTile(MahjongHonorType.RedDragon),
new MahjongHonorTile(MahjongHonorType.WhiteDragon)
}
IEnumerable<MahjongTile> dragonTilesInHand = hand.Where(t => dragonTiles.Contains(t));
My Question: how should I define equality in the MahjongTile base class?
Since Object.Equals is virtual, the subclasses implementation override the method. No further code is needed.

Categories

Resources