How to compare T to T? - c#

I've got a generic class, which contains a value. This class stores a default value and I want to check, whether the stored value equals to the default one.
At first, I tried simply:
public bool IsDefault
{
get
{
return value == defaultValue;
}
}
But unfortunately (and surprisingly) that does not compile - compiler complains, that it cannot compare T to T. The second approach is:
public bool IsDefault
{
get
{
if (value == null)
return defaultValue == null;
else
return value.Equals(defaultValue);
}
}
It works, but I have a problem with strings, because a null string in my case equals to empty string, but the previous code does not cover that.
I may specialize the class for strings, but I'd avoid that if it is not necessary. Is there a way to compare two T's in a generic way?
Edit: in response to comments
Let's assume, that the class looks like the following:
public class MyClass<T>
{
private T value;
private T defaultValue;
public MyClass(T newDefault)
{
value = newDefault;
defaultValue = newDefault;
}
public T Value
{
get
{
return value;
}
set
{
this.value = value;
}
}
public bool IsDefault
{
get
{
// ?
}
}
}

The constructor of your class should take an IEqualityComparer<T> as a parameter, and an overload could pass in the EqualityComparer<T>.Default. Store it and use to test for equality. In the case of strings, pass in an IEqualityComparer<string> that considers "" == null.
Like this:
class Example<T>
{
private readonly IEqualityComparer<T> comparer;
private readonly T defaultValue;
private T value;
public Example(T value, T defaultValue, IEqualityComparer<T> comparer)
{
this.value = value;
this.defaultValue = defaultValue;
this.comparer = comparer;
}
public Example(T value, T defaultValue)
: this(value, defaultValue, EqualityComparer<T>.Default)
{
}
public Example(T value)
: this(value, default(T))
{
}
public Example()
: this (default(T))
{
}
public bool IsDefault
{
get
{
if (value == null)
{
return defaultValue == null;
}
else
{
return comparer.Equals(value, defaultValue);
}
}
}
}

Related

Can I return a different type from a function in a generic class depending on if the generic type used for the class is a value or a reference type?

I want to return a Nullable<Value> from a function in a generic class if Value is a value type, and just 'Value' if value is already a reference type.
I've been trying to work with where clauses to achieve this, but I can't seem to use a where class on a non-generic function, even in a generic class.
public class HashTable<Key, Value>
{
private List<ValueSlot> valueSlots = new List<ValueSlot>();
private struct ValueSlot
{
public bool hasValue;
public List<KeyValuePair<Key, Value>> values;
}
//...
public Nullable<Value> TryGetValue(Key key) where Value : struct
{
(bool result, Value value) = TryGetValue(valueSlots, key);
if (result == true)
{
Nullable<Value> myVal = value;
return myVal;
}
else
{
return null;
}
}
public Value TryGetValue(Key key) where Value : class
{
(bool result, Value value) = TryGetValue(valueSlots, key);
return result == true ? value : (Value)null;
}
private (bool, Value) TryGetValue(List<ValueSlot> valueSlots, Key key)
{
//...
}
//...
}
Unfortunately, this doesn't compile an generates a bunch of errors. I would rather not resort to returning tuples out from the class. Is there a simple way to make this approach work that I am missing? I've been trying to get this to work for nearly a week now...
Polymorphism by return type is not supported by C# yet. Generic type constraint is a hint to the compiler and not making method signatures different.
I'd suggest using Maybe<T> so that you can do this:
public class HashTable<Key, Value>
{
public Maybe<Value> TryGetValue(Key key)
{
(bool result, Value value) = TryGetValue(valueSlots, key);
if (result == true)
{
return new Maybe<Value>(value); // or value.ToMaybe() // with the extension method
}
else
{
return Maybe<Value>.Nothing;
}
}
}
This works regardless of what type the Value is.
Here's the implementation that I use:
public static class MaybeEx
{
public static Maybe<T> ToMaybe<T>(this T value)
{
return new Maybe<T>(value);
}
public static T GetValue<T>(this Maybe<T> m, T #default) => m.HasValue ? m.Value : #default;
public static T GetValue<T>(this Maybe<T> m, Func<T> #default) => m.HasValue ? m.Value : #default();
public static Maybe<U> Select<T, U>(this Maybe<T> m, Func<T, U> k)
{
return m.SelectMany(t => k(t).ToMaybe());
}
public static Maybe<U> SelectMany<T, U>(this Maybe<T> m, Func<T, Maybe<U>> k)
{
if (!m.HasValue)
{
return Maybe<U>.Nothing;
}
return k(m.Value);
}
public static Maybe<V> SelectMany<T, U, V>(this Maybe<T> #this, Func<T, Maybe<U>> k, Func<T, U, V> s)
{
return #this.SelectMany(x => k(x).SelectMany(y => s(x, y).ToMaybe()));
}
}
public class Maybe<T>
{
public class MissingValueException : Exception { }
public readonly static Maybe<T> Nothing = new Maybe<T>();
private T _value;
public T Value
{
get
{
if (!this.HasValue)
{
throw new MissingValueException();
}
return _value;
}
private set
{
_value = value;
}
}
public bool HasValue { get; private set; }
public Maybe()
{
HasValue = false;
}
public Maybe(T value)
{
Value = value;
HasValue = true;
}
public T ValueOrDefault(T #default) => this.HasValue ? this.Value : #default;
public T ValueOrDefault(Func<T> #default) => this.HasValue ? this.Value : #default();
public static implicit operator Maybe<T>(T v)
{
return v.ToMaybe();
}
public override string ToString()
{
return this.HasValue ? this.Value.ToString() : "<null>";
}
public override bool Equals(object obj)
{
if (obj is Maybe<T>)
return Equals((Maybe<T>)obj);
return false;
}
public bool Equals(Maybe<T> obj)
{
if (obj == null) return false;
if (!EqualityComparer<T>.Default.Equals(_value, obj._value)) return false;
if (!EqualityComparer<bool>.Default.Equals(this.HasValue, obj.HasValue)) return false;
return true;
}
public override int GetHashCode()
{
int hash = 0;
hash ^= EqualityComparer<T>.Default.GetHashCode(_value);
hash ^= EqualityComparer<bool>.Default.GetHashCode(this.HasValue);
return hash;
}
public static bool operator ==(Maybe<T> left, Maybe<T> right)
{
if (object.ReferenceEquals(left, null))
{
return object.ReferenceEquals(right, null);
}
return left.Equals(right);
}
public static bool operator !=(Maybe<T> left, Maybe<T> right)
{
return !(left == right);
}
}
I believe what you are looking for is a Maybe Monad. It requires some work. But it is worth it imho. Implementation for Maybe Monad for C# is well described here.
You need to make some compromises to make this work:
public V? GetNullable<V>(Key key) where V : struct, Value
{
(bool result, Value value) = TryGetValue(valueSlots, key);
return result ? (V)value : (V?)null;
}
public V GetValueOrNull<V>(Key key) where V : class, Value
{
(bool result, Value value) = TryGetValue(valueSlots, key);
return result == true ? (V)value : null;
}
You must give different names to the two methods, and provide the type as parameter every time you call them:
var h1 = new HashTable<int, DateTime>(); // Value Type
DateTime? date = h1.GetNullable<DateTime>(1);
var h2 = new HashTable<int, Exception>(); // Reference Type
Exception ex = h2.GetValueOrNull<Exception>(1);
I guess that this defeats the purpose though.

Get name of a property and declaring class

How can I use reflection to get the name and declaring class of a property of a generic type. The purpose is to get an exception if I read a property where nothing has been written so far. One of the problems is that the check must be independent of the declaring class.
value.GetType().DeclaringType is always null.
using System;
namespace TestCodeContract
{
public struct CheckForNull<T> where T : struct
{
private T? backingField;
public static implicit operator T(CheckForNull<T> value)
{
if (!(value.backingField.HasValue))
{
var t1 = value.GetType().DeclaringType; // always null.
var propertyName = "Delta"; // TODO get from Reflection
var className = "ContractClass"; // TODO get from Reflection
var msg = String.Format("Proprety '{0}' in class '{1}' is not initialized", propertyName, className);
throw new ApplicationException(msg);
}
return value.backingField.Value;
}
public static implicit operator CheckForNull<T>(T value)
{
return new CheckForNull<T> { backingField = value };
}
}
public class ContractClass
{
public CheckForNull<int> Delta { get; set; }
public void Test1()
{
int x = Delta; // Wanted: "Property 'Delta' in class 'ContractClass' is not initialized"
}
}
}
No, you can't do it like that. I would suggest something like this instead:
// You could do this without the constraint, with a bit of extra work.
public class ReadOnlyAfterWrite<T> where T : struct
{
private T? value;
private readonly string property;
private readonly string type;
public ReadOnlyAfterWrite(string property, string type)
{
this.property = property;
this.type = type;
}
public T Value
{
get
{
if (value == null)
{
// Use type and property here
throw new InvalidOperationException(...);
}
return (T) value;
}
set { this.value = value; }
}
}
public class ContractClass
{
// This is what I'd do in C# 6. Before that, probably just use string literals.
private readonly ReadOnlyAfterWrite<int> delta =
new ReadOnlyAfterWrite(nameof(Delta), nameof(ContractClass));
public int Delta
{
get { return delta.Value; }
set { delta.Value = value; }
}
}
While it's not terribly clean in implementation, I think it's a better public API - the fact that it's guarded is invisible to the caller, who just sees an int property.

Constrain generic to be a nullable type

I'm looking for sample usage something like this:
Foo<string> stringFoo = new Foo<string>("The answer is");
Foo<int> intFoo = new Foo<int>(42);
// The Value of intFoo & stringFoo are strongly typed
stringFoo.Nullify();
intFoo.Nullify();
if (stringFoo == null && intFoo == null)
MessageBox.Show("Both are null);
Given this class Foo, I can auto-wrap T into a nullable:
public class Foo1<T>
where T : struct
{
private T? _value;
public Foo(T? initValue)
{
_value = initValue;
}
public T? Value { get { return _value; } }
public void Nullify { _value = null; }
}
This works for primitives, but not with String or other classes.
Next flavor works for strings, but not primitives:
public class Foo2<T>
{
private T _value;
public Foo(T initValue)
{
_value = initValue;
}
public T Value { get { return _value; } }
public void Nullify { _value = default(T); }
}
I could use Nullable<int> for Foo2 and the code would work like this:
Foo2<int?> intFoo = new Foo<int?>(42);
But this is error prone because it fails for Foo2. If I could constrain T to be types that support nullability then that would be fine.
So after all of that, is there any way to constrain T to be a nullable type?
Some additional notes: .NET 4.0, VS2010. And I did find one similar question to this on here, but without a succesful answer.
There's no constraint you can apply for this, but you can test for it at execution time:
if (default(T) != null)
{
throw new SomeAppropriateException(typeof(T) + " is not a nullable type");
}
You could even put that into a static constructor, which would make sure it only executed once per constructed type - and anyone trying to use Foo<int> anywhere would have a hard time ignoring the TypeInitializerException. That's not terribly friendly for a public API, but I think it's reasonable for an internal one.
EDIT: There is one horrible way of making it harder to create instances of Foo<int>... you could use the ghastly code in this blog post (using overload resolution rules along with default parameters and a couple of constrained generic types) and mark the overload which aims at a non-nullable value type as obsolete with an error. That way, Foo<int> would still be a valid type, but you'd be hard-pressed to create an instance of it. I'm not going to recommend that you do this though...
You might be able to make the constructor of Foo<T> internal, and require that new instances can only be created through a factory class:
public class Foo<T>
{
private T value;
internal Foo(T value)
{
this.value = value;
}
public void Nullify()
{
this.value = default(T);
}
public T Value { get { return this.value; } }
}
public class Foo
{
public static Foo<T> Create<T>(T value) where T : class
{
return new Foo<T>(value);
}
public static Foo<T?> Create<T>(T? value) where T : struct
{
return new Foo<T?>(value);
}
}
I don't like it as much as the syntax of Foo1, but here is Foo3:
public class Foo3<T>
where T : struct
{
private T _value;
private T _nullValue;
public Foo3(T initValue)
: this(initValue, default(T))
{
}
public Foo3(T initValue, T nullValue)
{
_value = initValue;
_nullValue = nullValue;
}
public T Value { get { return _value; } }
public bool IsNull
{
get
{
return object.Equals(_value, _nullValue);
}
}
public void Nullify() { _value = _nullValue; }
}
And then my usage becomes:
Foo3<string> stringFoo = new Foo<string>("The answer is");
Foo3<int> intFoo = new Foo<int>(42, int.MinValue);
stringFoo.Nullify();
intFoo.Nullify();
if (stringFoo.IsNull && intFoo.IsNull)
MessageBox.Show("Both are null);
This is still error prone because getting the Value property of Foo3 (and Foo2) is not straightforward. Foo1 was the best because automatically wrapped the Value will null support.
I might just need ValueTypeFoo and ObjectFoo and deal with two versons.

Create an IUserType for a generic option class with nhibernate

I'm looking for a way to create an IUserType for an option type class. Here is the option type class code:
public static class Option
{
public static Option<T> Some<T>(T value)
{
return new Option<T>(value);
}
public static Option<T> None<T>()
{
return new Option<T>();
}
}
public class Option<T>
{
public Option(T value)
{
_value = value;
_isSome = true;
}
public Option()
{
_isSome = false;
}
T _value;
bool _isSome;
public bool IsSome
{
get { return _isSome; }
}
public bool IsNone
{
get { return !_isSome; }
}
public T Value
{
get { return _value; }
}
public T ValueOrDefault(T value)
{
if (IsSome)
return Value;
return value;
}
public override bool Equals(object obj)
{
var temp = obj as Option<T>;
if (temp == null)
return false;
if (this.IsNone && temp.IsNone)
return true;
if (this.IsSome && temp.IsSome)
{
var item1 = this.Value;
var item2 = temp.Value;
return object.Equals(item1, item2);
}
return false;
}
public override int GetHashCode()
{
if (this.IsNone)
return base.GetHashCode() + 23;
return base.GetHashCode() + this.Value.GetHashCode() + 23;
}
}
It is basically just a wrapper around whatever type of T the user wants. It should end up mapping a nullable version of T. I have been unable to find any documentation on doing something like this.
Any help is appreciated.
Here are some articles I have used for the basis of my IUserType classes:
Implementing Custom Types in NHibernate
Generic NHibernate User Type Base Class
Implementing Money Type NHibernate

Creating a generic method in C#

I am trying to combine a bunch of similar methods into a generic method. I have several methods that return the value of a querystring, or null if that querystring does not exist or is not in the correct format. This would be easy enough if all the types were natively nullable, but I have to use the nullable generic type for integers and dates.
Here's what I have now. However, it will pass back a 0 if a numeric value is invalid, and that unfortunately is a valid value in my scenarios. Can somebody help me out? Thanks!
public static T GetQueryString<T>(string key) where T : IConvertible
{
T result = default(T);
if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false)
{
string value = HttpContext.Current.Request.QueryString[key];
try
{
result = (T)Convert.ChangeType(value, typeof(T));
}
catch
{
//Could not convert. Pass back default value...
result = default(T);
}
}
return result;
}
What if you specified the default value to return, instead of using default(T)?
public static T GetQueryString<T>(string key, T defaultValue) {...}
It makes calling it easier too:
var intValue = GetQueryString("intParm", Int32.MinValue);
var strValue = GetQueryString("strParm", "");
var dtmValue = GetQueryString("dtmPatm", DateTime.Now); // eg use today's date if not specified
The downside being you need magic values to denote invalid/missing querystring values.
I know, I know, but...
public static bool TryGetQueryString<T>(string key, out T queryString)
What about this? Change the return type from T to Nullable<T>
public static Nullable<T> GetQueryString<T>(string key) where T : struct, IConvertible
{
T result = default(T);
if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false)
{
string value = HttpContext.Current.Request.QueryString[key];
try
{
result = (T)Convert.ChangeType(value, typeof(T));
}
catch
{
//Could not convert. Pass back default value...
result = default(T);
}
}
return result;
}
Convert.ChangeType() doesn't correctly handle nullable types or enumerations in .NET 2.0 BCL (I think it's fixed for BCL 4.0 though). Rather than make the outer implementation more complex, make the converter do more work for you. Here's an implementation I use:
public static class Converter
{
public static T ConvertTo<T>(object value)
{
return ConvertTo(value, default(T));
}
public static T ConvertTo<T>(object value, T defaultValue)
{
if (value == DBNull.Value)
{
return defaultValue;
}
return (T) ChangeType(value, typeof(T));
}
public static object ChangeType(object value, Type conversionType)
{
if (conversionType == null)
{
throw new ArgumentNullException("conversionType");
}
// if it's not a nullable type, just pass through the parameters to Convert.ChangeType
if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
// null input returns null output regardless of base type
if (value == null)
{
return null;
}
// it's a nullable type, and not null, which means it can be converted to its underlying type,
// so overwrite the passed-in conversion type with this underlying type
conversionType = Nullable.GetUnderlyingType(conversionType);
}
else if (conversionType.IsEnum)
{
// strings require Parse method
if (value is string)
{
return Enum.Parse(conversionType, (string) value);
}
// primitive types can be instantiated using ToObject
else if (value is int || value is uint || value is short || value is ushort ||
value is byte || value is sbyte || value is long || value is ulong)
{
return Enum.ToObject(conversionType, value);
}
else
{
throw new ArgumentException(String.Format("Value cannot be converted to {0} - current type is " +
"not supported for enum conversions.", conversionType.FullName));
}
}
return Convert.ChangeType(value, conversionType);
}
}
Then your implementation of GetQueryString<T> can be:
public static T GetQueryString<T>(string key)
{
T result = default(T);
string value = HttpContext.Current.Request.QueryString[key];
if (!String.IsNullOrEmpty(value))
{
try
{
result = Converter.ConvertTo<T>(value);
}
catch
{
//Could not convert. Pass back default value...
result = default(T);
}
}
return result;
}
You can use sort of Maybe monad (though I'd prefer Jay's answer)
public class Maybe<T>
{
private readonly T _value;
public Maybe(T value)
{
_value = value;
IsNothing = false;
}
public Maybe()
{
IsNothing = true;
}
public bool IsNothing { get; private set; }
public T Value
{
get
{
if (IsNothing)
{
throw new InvalidOperationException("Value doesn't exist");
}
return _value;
}
}
public override bool Equals(object other)
{
if (IsNothing)
{
return (other == null);
}
if (other == null)
{
return false;
}
return _value.Equals(other);
}
public override int GetHashCode()
{
if (IsNothing)
{
return 0;
}
return _value.GetHashCode();
}
public override string ToString()
{
if (IsNothing)
{
return "";
}
return _value.ToString();
}
public static implicit operator Maybe<T>(T value)
{
return new Maybe<T>(value);
}
public static explicit operator T(Maybe<T> value)
{
return value.Value;
}
}
Your method would look like:
public static Maybe<T> GetQueryString<T>(string key) where T : IConvertible
{
if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false)
{
string value = HttpContext.Current.Request.QueryString[key];
try
{
return (T)Convert.ChangeType(value, typeof(T));
}
catch
{
//Could not convert. Pass back default value...
return new Maybe<T>();
}
}
return new Maybe<T>();
}
I like to start with a class like this
class settings
{
public int X {get;set;}
public string Y { get; set; }
// repeat as necessary
public settings()
{
this.X = defaultForX;
this.Y = defaultForY;
// repeat ...
}
public void Parse(Uri uri)
{
// parse values from query string.
// if you need to distinguish from default vs. specified, add an appropriate property
}
This has worked well on 100's of projects. You can use one of the many other parsing solutions to parse values.

Categories