Now, what do I mean by accessing properties?
What if you need to tell some object to use a property and its value, but it may need to access this property several times and the value might change. The last is the crux of the problem here.
If you pass the property in using standard property accessors, you will get the value as it stands at that time. If the property is mutable then this maybe ok, but what if it's not or the mutable object is replaced?
Well, you could pass the object and a magic string and use reflection to access the property when the new objects needs access, but there is always a penalty to using this approach.
However, using Lambdas and the power of closures, you now have an alternative to this approach:
Take a look at the following code:
using System;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var vio = new SomeVeryImportantObject { VeryImportantProperty = "Top Secret" };
var moreImportantObject = new NeedInfoToWork();
moreImportantObject.SetAnothersPropertyToUseLaterUsingDelegates(() => vio.VeryImportantProperty);
moreImportantObject.SetAnothersPropertyToUseLaterUsingReflection(vio, "VeryImportantProperty");
vio.VeryImportantProperty = "Ok, not so important";
Console.WriteLine(moreImportantObject.GetValueNowUsingReflection());
Console.WriteLine(moreImportantObject.GetValueUsingClousers());
const int timesToAccess = 1000000;
var sw = Stopwatch.StartNew();
for (int i = 0; i < timesToAccess; i++)
{
var value = moreImportantObject.GetValueNowUsingReflection();
}
sw.Stop();
Console.WriteLine("Time Taken using reflection {0}ms", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for (int i = 0; i < timesToAccess; i++)
{
var value = moreImportantObject.GetValueUsingClousers();
}
sw.Stop();
Console.WriteLine("Time Taken using closures {0}ms", sw.ElapsedMilliseconds);
Console.ReadKey();
}
}
public class SomeVeryImportantObject
{
public string VeryImportantProperty { get; set; }
}
public class NeedInfoToWork
{
private Func_propertyAccess;
private object _objectToAccess;
private string _propertyName;
public void SetAnothersPropertyToUseLaterUsingDelegates(FuncpropertyAccess)
{
_propertyAccess = propertyAccess;
}
public void SetAnothersPropertyToUseLaterUsingReflection(Object objectToGetPropertyValueFrom, string propertyName)
{
_objectToAccess = objectToGetPropertyValueFrom;
_propertyName = propertyName;
}
public string GetValueNowUsingReflection()
{
return _objectToAccess.GetType()
.GetProperty(_propertyName)
.GetValue(_objectToAccess, null)
.ToString();
}
public string GetValueUsingClousers()
{
return _propertyAccess();
}
}
}
This produced the following results on my computer:
> Ok, not so important
> Ok, not so important
> Time Taken using reflection 2076ms
> Take Taken using closures 56ms
Enough said.
We have improved performance and removed the use of magic strings.