Trying to Compare Instance of Class Directly to a String - c#

How can I make a class like this:
public class Foo
{
private string m_value;
public string Value { get { return m_value; } set { m_value = value; } }
public Foo()
{
m_value = "";
}
}
be directly comparable with a string without needing to access it's .Value property so that I can do:
Foo m_foo = new Foo();
m_foo = "someString";
if(m_foo == "someString")
{
Console.Writeline("It Worked!");
}
I'm not sure if this is even possible.

You can overload the == operator (the compiler also requires you overload '!=', 'Equals', and 'GetHashCode')
public class Foo
{
private string m_value;
public string Value { get { return m_value; } set { m_value = value; } }
public Foo()
{
m_value = "";
}
public override bool Equals(object obj)
{
return this.Value == obj.ToString();
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public static bool operator ==(Foo a, string b)
{
return a.Value == b;
}
public static bool operator !=(Foo a, string b)
{
return a.Value != b;
}
}
I'm not sure if all of that effort is worth it though, when you could just write:
if(m_foo.Value == "someString")

Related

How to Overload Get Operator in C#?

I have a class which stores value.
public class Entry<T>
{
private T _value;
public Entry() { }
public Entry(T value)
{
_value = value;
}
public T Value
{
get { return _value; }
set { _value = value; }
}
// overload set operator.
public static implicit operator Entry<T>(T value)
{
return new Entry<T>(value);
}
}
To utilize this class:
public class Exam
{
public Exam()
{
ID = new Entry<int>();
Result = new Entry<int>();
// notice here I can assign T type value, because I overload set operator.
ID = 1;
Result = "Good Result.";
// this will throw error, how to overload the get operator here?
int tempID = ID;
string tempResult = Result;
// else I will need to write longer code like this.
int tempID = ID.Value;
string tempResult = Result.Value;
}
public Entry<int> ID { get; set; }
public Entry<string> Result { get; set; }
}
I'm able to overload the set operator which I can straightaway do "ID = 1".
But when I do "int tempID = ID;", it will throw error.
How to overload the get operator so I can do "int tempID = ID;" instead of "int tempID = ID.Value;"?
Simple, add another implicit operator but for the other direction!
public class Entry<T>
{
private T _value;
public Entry() { }
public Entry(T value)
{
_value = value;
}
public T Value
{
get { return _value; }
set { _value = value; }
}
public static implicit operator Entry<T>(T value)
{
return new Entry<T>(value);
}
public static implicit operator T(Entry<T> entry)
{
return entry.Value;
}
}
And usage is a breeze:
void Main()
{
Entry<int> intEntry = 10;
int val = intEntry;
}

Newtonsoft.json Error converting value 333 to type

Newtonsoft.json does not seem to be able to convert int to my nInt struct. I'm not sure why. The purpose of my struct is to allow int to be set to null, but not actually be null and instead default to 0.
Here is my code:
nInt:
/// <summary>
/// Non-nullable int. Defaults to 0.
/// </summary>
public struct nInt
{
public nInt(int? value)
: this()
{
Value = value ?? 0;
}
private void deNullify()
{
Value = Value ?? 0;
}
public int? Value
{
get;
private set;
}
public static implicit operator nInt(int value)
{
return new nInt(value);
}
public static implicit operator nInt(int? value)
{
return new nInt(value);
}
public static implicit operator int?(nInt value)
{
return value.Value ?? 0;
}
public static implicit operator int(nInt value)
{
return value.Value ?? 0;
}
public override bool Equals(object other)
{
deNullify();
return Value.Equals(other);
}
public override int GetHashCode()
{
deNullify();
return Value.GetHashCode();
}
public Type GetType()
{
return typeof(int?);
}
public int GetValueOrDefault(int defaultValue)
{
deNullify();
return Value.GetValueOrDefault(defaultValue);
}
public bool HasValue
{
get { deNullify(); return Value.HasValue; }
}
public override string ToString()
{
deNullify();
return Value.ToString();
}
}
nInt usage:
public class TotalCountObject
{
public nInt totalCount { get; set; }
}
TotalCountObject tco = JsonConvert.DeserializeObject<TotalCountObject>(jsonString, jsonSerializerSettings);
// here is where i get Error converting value 333 to type 'nInt'.
You don't need to create your own type to do this. You can use the NullValueHandling options in JSON.NET to ignore nulls for non-nullable types. For example:
public class TotalCountObject
{
[JsonProperty(NullValueHandling = NullValueHanding.Ignore)]
public int totalCount { get; set; }
}
Since the default value of int is 0, when this property is ignored, its value will be zero.
You can also set this property in JsonSerializerSettings:
var settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
TotalCountObject tco = JsonConvert.DeserializeObject<TotalCountObject>(
jsonString, jsonSerializerSettings);
Although that may not be a route you want to take if you don't want the NullValueHandling to apply to all properties.

Global type aliases in C#

let me start right away with the code:
class Item {
public int highestBuyOffer;
public int lowestSellOffer;
[...]
}
I would like to prevent people using this class from accidently assigning a buy offer value to a sell offer value and the other way round (like someBuyOffer = someSellOffer). That's why I want to create my own types:
class Item {
public BuyOffer highestBuyOffer;
public SellOffer lowestSellOffer;
[...]
}
Creating a struct for it seems overkill, as these both of values should behave exactly like an int.
The using directive is not what I want because:
It is only valid for one file
It does not count as a type, it's just a synonym
I made this class to cover identical needs:
public class NamedInt : IComparable<int>, IEquatable<int>
{
internal int Value { get; }
protected NamedInt() { }
protected NamedInt(int val) { Value = val; }
protected NamedInt(string val) { Value = Convert.ToInt32(val); }
public static implicit operator int (NamedInt val) { return val.Value; }
public static bool operator ==(NamedInt a, int b) { return a?.Value == b; }
public static bool operator ==(NamedInt a, NamedInt b) { return a?.Value == b?.Value; }
public static bool operator !=(NamedInt a, int b) { return !(a==b); }
public static bool operator !=(NamedInt a, NamedInt b) { return !(a==b); }
public bool Equals(int other) { return Equals(new NamedInt(other)); }
public override bool Equals(object other) {
if ((other.GetType() != GetType() && other.GetType() != typeof(string))) return false;
return Equals(new NamedInt(other.ToString()));
}
private bool Equals(NamedInt other) {
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Equals(Value, other.Value);
}
public int CompareTo(int other) { return Value - other; }
public int CompareTo(NamedInt other) { return Value - other.Value; }
public override int GetHashCode() { return Value.GetHashCode(); }
public override string ToString() { return Value.ToString(); }
}
And to consume it in your case:
public class BuyOffer: NamedInt {
public BuyOffer(int value) : base(value) { }
public static implicit operator BuyOffer(int value) { return new BuyOffer(value); }
}
public class SellOffer: NamedInt {
public SellOffer(int value) : base(value) { }
public static implicit operator SellOffer(int value) { return new SellOffer(value); }
}
If you need to be able to serialize it (Newtonsoft.Json), let me know and I'll add the code.

HashSet<T> quickly checking if identity exists by T.identity

I have an entity called Feature which contains a value identity called FeatureIdentity.
I have a list of these entities, and i want to quickly determine if the identity already exists.
The kicker is i need to be able to compare by the FeatureIdentity and not be the Feature, the Contains procedure on lists is checking against a provided T parameter.
So I am currently doing the code:
public class SomeClass
{
HashSet<Feature> features = new HashSet<Feature>();
public void SetRequirement(FeatureIdentity feature, FeatureIdentity requires)
{
if (ContainsFeature(feature) == false || ContainsFeature(requires) == false)
{
// throw
}
this.requirements.Add(feature, requires);
}
bool ContainsFeature(FeatureIdentity identity)
{
return this.features.Where(x => x.Id.Equals(identity)).Count() > 0;
}
}
Does Linq optimize this, or is this there a correct optimal way of checking if the item exists?
public class Feature
{
public Feature(FeatureIdentity id, string name)
{
this.id = id;
this.name = name;
}
FeatureIdentity id;
string name;
FeatureIdentity Id
{
get { return this.id; }
}
}
public class FeatureIdentity : IEquatable<FeatureIdentity>
{
private readonly string sku;
public FeatureIdentity(string sku)
{
this.sku = sku;
}
public bool Equals(FeatureIdentity other)
{
return this.sku == other.sku;
}
public string Sku
{
get { return this.sku; }
}
public override int GetHashCode()
{
return this.sku.GetHashCode();
}
}
with ctor public HashSet(), HashSet<Feature> is using EqualityComparer<Feature>.Default as default Comparer.
if you use HashSet<Feature>, you should implement IEquatable<Feature> and override GetHashCode.
public class Feature: IEquatable<Feature>
{
public bool Equals(Feature other)
{
return this.id.Equals(other.id);
}
public override int GetHashCode()
{
return this.id.GetHashCode();
}
}
then you can try following workaround which waster a temp object from heap.
bool ContainsFeature(FeatureIdentity identity)
{
return this.features.Contain(new Feature(identity, null));
}

Variable class properties due to specific constructor in C#

Suppose class A as:
public class A
{
private string _str;
private int _int;
public A(string str)
{
this._str = str;
}
public A(int num)
{
this._int = num;
}
public int Num
{
get
{
return this._int;
}
}
public string Str
{
get
{
return this._str;
}
}
}
I want to hide Str property when i construct class A as
new A(2)
and want to hide Num property when i construct class A as
new A("car").
What should i do?
That isn't possible with a single class. An A is an A, and has the same properties - regardless of how it is constructed.
You could have 2 subclasses of abstract A, and a factory method...
public abstract class A
{
class A_Impl<T> : A
{
private T val;
public A_Impl(T val) { this.val = val; }
public T Value { get { return val; } }
}
public static A Create(int i) { return new A_Impl<int>(i); }
public static A Create(string str) { return new A_Impl<string>(str); }
}
But : the caller will not know about the value unless they cast it.
use generics
public class A<T>
{
private T _value;
public A(T value)
{
this._value= value;
}
public TValue
{
get
{
return this._value;
}
}
}

Categories