Should C# have a lazy keyword to make lazy initialization easier?
E.g.
public lazy string LazyInitializeString = GetStringFromDatabase();
instead of
private string _backingField;
public string LazyInitializeString
{
get
{
if (_backingField == null)
_backingField = GetStringFromDatabase();
return _backingField;
}
}
I don't know about a keyword but it now has a System.Lazy<T> type.
It is officially part of .Net Framework 4.0.
It allows lazy loading of a value for a member.
It supports a lambda expression or a method to provide a value.
Example:
public class ClassWithLazyMember
{
Lazy<String> lazySource;
public String LazyValue
{
get
{
if (lazySource == null)
{
lazySource = new Lazy<String>(GetStringFromDatabase);
// Same as lazySource = new Lazy<String>(() => "Hello, Lazy World!");
// or lazySource = new Lazy<String>(() => GetStringFromDatabase());
}
return lazySource.Value;
}
}
public String GetStringFromDatabase()
{
return "Hello, Lazy World!";
}
}
Test:
var obj = new ClassWithLazyMember();
MessageBox.Show(obj.LazyValue); // Calls GetStringFromDatabase()
MessageBox.Show(obj.LazyValue); // Does not call GetStringFromDatabase()
In above Test code, GetStringFromDatabase() gets called only once. I think that is exactly what you want.
Edit:
After having comments from #dthorpe and #Joe, all I can say is following is the shortest it can be:
public class ClassWithLazyMember
{
Lazy<String> lazySource;
public String LazyValue { get { return lazySource.Value; } }
public ClassWithLazyMember()
{
lazySource = new Lazy<String>(GetStringFromDatabase);
}
public String GetStringFromDatabase()
{
return "Hello, Lazy World!";
}
}
Because following does not compile:
public Lazy<String> LazyInitializeString = new Lazy<String>(() =>
{
return GetStringFromDatabase();
});
And that property is type of Lazy<String> not String. You you always need to access it's value using LazyInitializeString.Value.
And, I am open for suggestions on how to make it shorter.
Have you considered using System.Lazy<T>?
public Lazy<String> LazyInitializeString = new Lazy<String>(() =>
{
return GetStringFromDatabase();
});
(This does have the disadvantage that you need to use LazyInitializeString.Value instead of just LazyInitializeString.)
Okay, you say in a comment that Lazy<T> won't suffice for you because it's readonly and you have to call .Value on it.
Still, it's clear that we want something along those lines - we already have a syntax for describing an action that is to be called, but not called immediately (indeed we have three; lambda, delegate creation and bare method name as a shortcut to the latter - the last thing we need is a fourth).
But we can quickly put together something that does that.
public enum SettableLazyThreadSafetyMode // a copy of LazyThreadSafetyMode - just use that if you only care for .NET4.0
{
None,
PublicationOnly,
ExecutionAndPublication
}
public class SettableLazy<T>
{
private T _value;
private volatile bool _isCreated;
private readonly Func<T> _factory;
private readonly object _lock;
private readonly SettableLazyThreadSafetyMode _mode;
public SettableLazy(T value, Func<T> factory, SettableLazyThreadSafetyMode mode)
{
if(null == factory)
throw new ArgumentNullException("factory");
if(!Enum.IsDefined(typeof(SettableLazyThreadSafetyMode), mode))
throw new ArgumentOutOfRangeException("mode");
_lock = (_mode = mode) == SettableLazyThreadSafetyMode.None ? null : new object();
_value = value;
_factory = factory;
_isCreated = true;
}
public SettableLazy(Func<T> factory, SettableLazyThreadSafetyMode mode)
:this(default(T), factory, mode)
{
_isCreated = false;
}
public SettableLazy(T value, SettableLazyThreadSafetyMode mode)
:this(value, () => Activator.CreateInstance<T>(), mode){}
public T Value
{
get
{
if(!_isCreated)
switch(_mode)
{
case SettableLazyThreadSafetyMode.None:
_value = _factory.Invoke();
_isCreated = true;
break;
case SettableLazyThreadSafetyMode.PublicationOnly:
T value = _factory.Invoke();
if(!_isCreated)
lock(_lock)
if(!_isCreated)
{
_value = value;
Thread.MemoryBarrier(); // ensure all writes involved in setting _value are flushed.
_isCreated = true;
}
break;
case SettableLazyThreadSafetyMode.ExecutionAndPublication:
lock(_lock)
{
if(!_isCreated)
{
_value = _factory.Invoke();
Thread.MemoryBarrier();
_isCreated = true;
}
}
break;
}
return _value;
}
set
{
if(_mode == SettableLazyThreadSafetyMode.None)
{
_value = value;
_isCreated = true;
}
else
lock(_lock)
{
_value = value;
Thread.MemoryBarrier();
_isCreated = true;
}
}
}
public void Reset()
{
if(_mode == SettableLazyThreadSafetyMode.None)
{
_value = default(T); // not strictly needed, but has impact if T is, or contains, large reference type and we really want GC to collect.
_isCreated = false;
}
else
lock(_lock) //likewise, we could skip all this and just do _isCreated = false, but memory pressure could be high in some cases
{
_value = default(T);
Thread.MemoryBarrier();
_isCreated = false;
}
}
public override string ToString()
{
return Value.ToString();
}
public static implicit operator T(SettableLazy<T> lazy)
{
return lazy.Value;
}
public static implicit operator SettableLazy<T>(T value)
{
return new SettableLazy<T>(value, SettableLazyThreadSafetyMode.ExecutionAndPublication);
}
}
Adding some more constructor overloads is left as an exercise to the reader :)
This will more than suffice:
private SettableLazy<string> _backingLazy = new SettableLazy<string>(GetStringFromDatabase);
public string LazyInitializeString
{
get
{
return _backingLazy;
}
set
{
_backingLazy = value;
}
}
Personally, I'm not overjoyed at the implicit operators, but they do show your requirements can be met. Certainly no need for another language feature.
Related
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.
Suppose that I have the following class:
public class IntBagWithLock
{
private readonly lockObject = new object();
private bool assigned = false;
private int data1;
private int data2;
public int? Data1
{
get { lock (lockObject) { return assigned ? data1 : (int?)null; } }
}
public int? Data2
{
get { lock (lockObject) { return assigned ? data2 : (int?)null; } }
}
public bool Assigned { get { lock(lockObject) { return assigned; } }
public bool TrySetData(int value1, int value2)
{
lock (lockObject)
{
if (assigned) return false;
data1 = value1;
data2 = value2;
assigned = true;
return true;
}
}
public bool IsEquivalentTo(IntBagWithLock other)
{
if (ReferenceEquals(this, other)) return true;
if (ReferenceEquals(other, null)) return false;
lock (lockObject)
{
if (!assigned) return false;
lock (other.lockObject)
{
return other.assigned && other.data1 == data1 && other.data2 == data2;
}
}
}
}
The problem I am worried about here is that, because of the way that IsEquivalentTo is implemented, I could be left with a deadlock condition, if a thread invoked item1.IsEquivalentTo(item2) and acquired item1's lock, and another invoked item2.IsEquivalentTo(item1) and acquired item2.
What should I do to ensure, as much as possible, that such deadlocks cannot happen?
UPDATE 2: The code sample has been modified to be closer to what I actually have. I think that all answers are still valid.
Normally you give an unique ID to every object, and then lock from lower id to higher id:
public class BagWithLock
{
// The first Id generated will be 1. If you want it to be 0, put
// here -1 .
private static int masterId = 0;
private readonly object locker = new object();
private readonly int id = Interlocked.Increment(ref masterId);
public static void Lock(BagWithLock bwl1, BagWithLock bwl2, Action action)
{
if (bwl1.id == bwl2.id)
{
// same object case
lock (bwl1.locker)
{
action();
}
}
else if (bwl1.id < bwl2.id)
{
lock (bwl1.locker)
{
lock (bwl2.locker)
{
action();
}
}
}
else
{
lock (bwl2.locker)
{
lock (bwl1.locker)
{
action();
}
}
}
}
}
You use it like:
bool equals;
BagWithLock(bag1, bag2, () => {
equals = bag1.SequenceEquals(bag2);
});
so you pass an Action containing what you want to do inside the locks.
The Interlocked.Increment on a static masterId guarantees an unique id to each class. Note that there will be problem if you create more than 4 billion instances of this class. If you need to do it, use long.
Since OP mentioned data is Immutable, I think no need of locks at all here, `volatile' should do the trick.
public class BagWithLock
{
private volatile object data;
public object Data
{
get { lock return data; }
set { data = value; }
}
public bool IsEquivalentTo(BagWithLock other)
{
return object.Equals(data, other.data);
}
}
This should be threadsafe. if am wrong pls correct me.
i donno why you lock every time you do get or equal, but you can do:
public bool IsEquivalentTo(BagWithLock other)
{
object myData;
object otherData;
lock (lockObject)
myData = data;
lock (other.lockObject)
otherData = other.data;
return object.Equals(myData, otherData);
}
that way the items won't change while they are compared.
in general, this kind of locks has some drawbacks, and i think that i would have done a general static lockObject so you could only has on object at a time in a method that could be a race condition
UPDATE
according to your update i'll say you should use:
private static readonly object equalLock = new object();
public bool IsEquivalentTo(IntBagWithLock other)
{
lock(equalLock){
if (ReferenceEquals(this, other)) return true;
if (ReferenceEquals(other, null)) return false;
if (!assigned) return false;
return other.assigned && other.data1 == data1 && other.data2 == data2;
}
}
Maybe you could use the more costly, WaitHandle-derived locking objects (such as Mutex), and use WaitHandle.WaitAll() when you want several locks at once?
I have a simple form which takes a user data and save it to database. while it is working fine but seems pretty repetitive.. i am not sure if i can turn my code in some way that it checks for user input and save it in DB.
here is my code..
public void SaveUserData()
{
MWCompetitionContestantsDetails user = new MWCompetitionContestantsDetails();
MWCompetitionsEntryDetails entry = new MWCompetitionsEntryDetails();
if (!IsNullOrEmpty(firstNameText.Value))
user.FirstName = firstNameText.Value;
if (!IsNullOrEmpty(lastNameText.Value))
user.LastName = lastNameText.Value;
if (!IsNullOrEmpty(emailText.Value))
user.UserEmailAddress = emailText.Value;
if (!IsNullOrEmpty(address1Text.Value))
user.Address1= address1Text.Value;
if (!IsNullOrEmpty(address2Text.Value))
user.Address2 = address2Text.Value;
if (!IsNullOrEmpty(cityText.Value))
user.City = cityText.Value;
if (!IsNullOrEmpty(provinceText.Value))
user.Province= provinceText.Value;
if (!IsNullOrEmpty(postCodeText.Value))
user.PostalCode = postCodeText.Value;
if (!IsNullOrEmpty(countryText.SelectedItem.Text))
user.Country = countryText.SelectedItem.Text;
user.Save();
}
public static bool IsNullOrEmpty<T>(T value)
{
if (typeof(T) == typeof(string))
return string.IsNullOrEmpty(value as string);
return value.Equals(default(T));
}
rather then looking for IsNullOrEmpty(data) on every fields, are there any suggestion to improve my code using Linq or anything..
your time much appreciated...
You can check If null or empty at the setter of your properties:
public class MWCompetitionContestantsDetails
{
private string _firstName;
public string FirstName
{
get
{
return this._firstName;
}
set
{
if(!IsNullOrEmpty(value))
{
this._firstName = value;
}
}
}
.........
public static bool IsNullOrEmpty<T>(T value)
{
if (typeof(T) == typeof(string))
return string.IsNullOrEmpty(value as string);
return value.Equals(default(T));
}
}
First of all, I'd like to say that I like oniant's and Adil Mammadov's solutions as they are deadly simple.
However I've already written code of fancy-shmancy approach I like to use in similar situations and I'd like to share it:
class Save<T> : ISave
{
private readonly System.Action<T> _assignValue;
private readonly System.Func<T> _getValue;
public void Do()
{
T value = _getValue();
if (!IsNullOrEmpty(value))
{
_assignValue(value);
}
}
public static Save<T> Value<T>(System.Func<T> getValue, System.Action<T> assignValue)
{
return new Save<T>(getValue, assignValue);
}
private Save(System.Func<T> getValue, System.Action<T> assignValue)
{
_getValue = getValue;
_assignValue = assignValue;
}
private static bool IsNullOrEmpty<T>(T value)
{
if (typeof(T) == typeof(string))
return string.IsNullOrEmpty(value as string);
return value.Equals(default(T));
}
}
internal interface ISave
{
void Do();
}
public static void SaveUserData()
{
MWCompetitionContestantsDetails user = new MWCompetitionContestantsDetails();
MWCompetitionsEntryDetails entry = new MWCompetitionsEntryDetails();
new List<ISave>
{
Save<string>.Value( () => firstNameText.Value, x => user.FirstName = x),
Save<string>.Value( () => lastNameText.Value, x => user.LastName = x),
Save<int>.Value( () => age.Value, x => user.Age = x),// int's supported :)
// etc
}
.ForEach(x => x.Do());
user.Save();
}
As long as your properties are string, you may use the object initialization :
MWCompetitionContestantsDetails user = new MWCompetitionContestantsDetails(){
FirstName = firstNameText.Value,
LastName = lastNameText.Value,
UserEmailAddress = emailText.Value,
Address1= address1Text.Value,
Address2 = address2Text.Value,
City = cityText.Value,
Province= provinceText.Value,
PostalCode = postCodeText.Value,
Country = countryText.SelectedItem.Text
};
user.Save();
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
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.