I'm trying to understand a code but I can't understand what 'p' var is.
public Prediction(Game kkk,bool checkit, params State[] checkStates)
: base(game, p => Manager.method(kkk, p))
{
this.checkit = checkit;
this.checkStates = checkStates;
}
The second class:
public PiratePrediction(Game game, System.Func<Pirate, T> valueExtractor)
{
this.game = game;
this.valueExtractor = valueExtractor;
this.predictedValues = new Dictionary<Pirate, T>();
this.totalPredictions = 0;
this.correctPredictions = 0;
}
found the class you're using on https://github.com/YoavKa/Skillz2016/blob/f23d25eed4baa9786cf517583ee867075a2f0505/API/Prediction/PiratePrediction.cs
the valueExtractor lambda is used from Update, and p comes from the keys of predictedValues dictionary.
public virtual void Update()
{
foreach (var pair in this.predictedValues)
{
if (pair.Key.State != PirateState.Lost && !EqualityComparer<T>.Default.Equals(pair.Value, default(T)))
{
this.totalPredictions++;
if (this.valueExtractor(pair.Key).Equals(pair.Value))
this.correctPredictions++;
}
}
this.predictedValues.Clear();
}
the p comes from the call to Predict method of PiratePrediction class. Because it's added to the predictedValues array.
public T Predict(Pirate p)
{
if (this.predictedValues.ContainsKey(p))
return this.predictedValues[p];
T predictedValue = this.predict(p);
if (EqualityComparer<T>.Default.Equals(predictedValue, default(T)))
return default(T);
this.predictedValues.Add(p, predictedValue);
return predictedValue;
}
p is a parameter being passed into your method. A Func<T, TOut> is a delegate, meaning a method signature.
Consider the following:
private class DisplayClass
{
public readonly Game kkk;
public DisplayyClass(Game kkk) { this.kkk = kkk; }
public T handler(Pirate p) { return Manager.method(kkk, p); }
}
public Prediction(Game kkk,bool checkit, params State[] checkStates)
: base(game, new DisplayClass(kkk).handler)
{
this.checkit= checkit;
this.checkStates = checkStates;
}
This is what the compiler does to your code when interpreting lambdas - it may be a good idea to pass your code through a decompiler to see the exact phrasing.
The p variable, as you can see in the expanded code, is a parameter into the method, and lambdas are just a shorthand way to pass methods which can then be invoked in other code.
// Somewhere in the base class...
void ExtractValue(Pirate p)
{
// ...
T value = this.valueExtractor(p);
// ...
}
When thus invoked, p will be the value passed in by that other code, and by definition of Func<Pirate, T>, will be of type Pirate.
Keep in mind that the code you're passing a lambda to can invoke the code inside your lambda multiple times, such as is the case with .Select. I suggest not only reading up on lambdas, but also their extensive use in the Linq namespace
A lambda expression is a declaration of an anonymous method. So imagine that this:
p => Manager.method(kkk, p)
is equal to this:
private T SomeMethod<T>(Pirate p)
{
return Manager.method(kkk, p);
}
You wouldn't be able to do the second snippet in your situation, however, because kkk is a local variable from the scope of where the lambda expression was declared, which means that while the lambda can use kkk, an explicit method declaration can't (See Closure). This is just one benefit of lambdas over declared methods.
Related
I want to get the Expression of the Expression-bodied Property. I have no idea how to do that;/ Here is the simple code snippet:
class TestTest
{
public int A { get; set; } = 5;
public int AX5 => A * 5;
}
public class Program
{
public static void Main()
{
var testObj = new TestTest();
Expression<Func<TestTest, int>> expr = (t) => t.AX5;
}
}
This code works, but AX5 is not marked as Expression, it is the simple Int32 property.
This is the result i want to get from the property:
The so called "Expression-Body" is just sugar to shorten function and property declarations. It does not have anything to do with the Expression<> type.
The 'expression-bodied' property in your class is equivalent to:
public int AX5
{
get { return A * 5; }
}
However, if you really wanted to capture this readonly property, you would have to retrieve the compiler generated get-method via reflection and then add an extra parameter to the Func<int> in order to pass the object-instance the property belongs to -> Func<TestTest, int>.
Here's an example:
class TestTest
{
public int A { get; set; } = 5;
public int AX5 => A * 5;
}
var f = typeof(TestTest).GetMethod("get_AX5")
.CreateDelegate(typeof(Func<TestTest, int>))
as Func<TestTest, int>;
Expression<Func<TestTest, int>> exp = instance => f(instance);
Note this is adding an additional function call to capture the new lambda-expression. Converting the get-method to an expression otherwise would get quite complicated.
This is not very useful though, usually you want to work the other way around and build Expression Trees to compile them to delegates later on.
Checkout the docs for Expression Trees for further information.
In Factory.Process(..) method, I want get hold of instances of MyClass that are being used in the lambda expression of the Func delegate. But, How?
Can someone help me find a way to do it.
Edit: This is an artificial example that demonstates my need. My intention behind this approach is that, I want to keep track of (or subscribe to) all the MyClass objects that are used in the delegate definition. So that, I can recalculate my total value whenever any MyClass object value is changed. Please suggest as to how to go about to solve this.
Note: Expression tree doesnt seem to help in my case because I cant modify my parameter type at this moment and it restricts the usage of my complex function definitions.
public class MyClass
{
public int Value;
public MyClass(int value)
{
Value = value;
}
}
public class TestClass
{
public void TestMethod()
{
var obj1 = new MyClass(10);
var obj2 = new MyClass(20);
Factory.Process(() => obj1.Value + obj2.Value);
}
}
public static class Factory
{
public static void Process(Func<int> function)
{
var total = function.Invoke();
// Here, apart from invoke, I want to access the all the instances of MyClass that are used in 'function'
// but how do I get to obj1 and obj2 objects through the 'function' delegate?
}
}
First of all, if you type an input parameter as just Func<T> it's not an expression, but just a lambda syntax for delegates.
If you want to be able to access the expression and do some reflection and/or analysis, you need to type your parameters as Expression<T>. For example: Expression<Func<int>>. This turns your expression into an expression tree.
Expression trees enable you to access the expression like a data structure. Once you've finished analyzing your expression tree, you can call yourExpression.Compile(), and this will compile your expression tree into a delegate that can be invoked as any other delegate (either named and anonymous ones).
For example, obj1 would be accessed this way:
public class MyClass
{
public int Value { get; set; }
}
static void Main(string[] args)
{
var obj1 = new MyClass { Value = 1 };
var obj2 = new MyClass { Value = 2 };
Expression<Func<int>> expr = () => obj1.Value + obj2.Value;
BinaryExpression binaryExpr = (BinaryExpression)expr.Body;
MemberExpression memberExpr = (MemberExpression)binaryExpr.Left;
MemberExpression fieldExpr = (MemberExpression)memberExpr.Expression;
ConstantExpression constantExpr = (ConstantExpression)fieldExpr.Expression;
dynamic value = constantExpr.Value;
MyClass some = value.obj1;
}
Update
OP said in some comment:
unfortunately, changing from parameter Func to
Expression> doesnt seem to work well in my situation because,
expression tree is restricting my function delegate definition from
using assignment operators and statement body.
My answer to this is you want an unexisting universal solution, because any other solution might compromise maintainability.
Maybe there's an alternative that will allow you to stay with delegates instead of expression trees: a delegate with an out parameter which would contain a collection of objects involved in there...
Since standard BCL Func delegates don't come with output parameters, you can declare your own Func delegate as follows:
public delegate TResult Func<out T>(out IDictionary<string, object> objects);
...and your delegate should set the so-called out parameter:
using System;
using System.Collections.Generic;
public class Program
{
public class MyClass
{
public int Value { get; set; }
}
public delegate void Func<out T>(out IDictionary<string, object> objects);
public static void Main()
{
Func<int> someFunc = (out IDictionary<string, object> objects) =>
{
var obj1 = new MyClass { Value = 1 };
var obj2 = new MyClass { Value = 2 };
int result = obj1.Value + obj2.Value;
objects = new Dictionary<string, object> { { "obj1", obj1 }, { "obj2", obj2 } };
};
IDictionary<string, object> objectsInFunc;
someFunc(out objectsInFunc);
}
}
As written, it cannot be done, because you're trying to access information about the exact code and would thus need to examine the incoming IL (since the actual C# code is gone after compilation).
However, it WOULD be possible using the metacode libraries of System.Linq.Expression namespace, but only if you swap out Func<int> for Expression<Func<int>>. With this, you would then be able to walk the expressions tree created by your lambda call. Using an Expression in place of another delegate type also tells the compiler to make an expression tree, rather than actually compiling the code, so this won't work if you pass a direct method or try to examine non-expression tree objects the same way.
You can if you change the parameter type of Process to Expression<Func<int>> expr:
public static void Process(Expression<Func<int>> expr)
{
Func<int> function = expr.Compile();
var total = function();
Expression left = ((BinaryExpression)expr.Body).Left;
Expression leftObjExpr = ((MemberExpression)left).Expression;
Expression<Func<MyClass>> leftLambda =
Expression.Lambda<Func<MyClass>>(leftObjExpr);
Func<MyClass> leftFunc = leftLambda.Compile();
MyClass obj1 = leftFunc();
int value = obj1.Value; // ==> 10
// Same with right operand...
}
Note that you can still invoke the function; you just have to compile the lambda expression to get a callable function.
However, this will only work with a binary expression. If you want to parse all kinds of expressions, this becomes quite complicated. You best solve this problem with the Visitor pattern.
Lets say i have the following code
private Func<T> _method;
public void SetExecutableMethod<T>(Func<T> methodParam)
{
_method = methodParam;
}
public T ExecuteMethod(object[] parameterValues)
{
//get the number of parameters _method has;
var methodCallExpression = _method.Body as MethodCallExpression;
var method = methodCallExpression.Method;
ParameterInfo[] methodParams = method.GetParameters();
//So i now have a list of parameters for the method call,
//How can i update the parameter values for each of these?
for (int i = 0; i < parameters.Count(); i++ )
{
methodParams[i] = ???''
}
return _method.Compile()();
}
public void InitAndTest()
{
SetExecutableMethod( () => _service.SomeMethod1("param1 placeholder", "param2 placeholder") );
T result1 = ExecuteMethod(new object[]{"Test1", "Test2"});
T result2 = ExecuteMethod(new object[]{"Test3", "Test4"}););
}
In the above code, i want to set a private variable to some Func that points to an anonymoust function and never have to set it again.
I then would like to be able to call ExecuteMethod(...) with different parameters. This method should update the parameter values of the variable _method and then invoke the method.
I can read the number of parameters and their values fine, i just am not sure how to set the values for those parameter? Any thoughts on this?
This is not the way to do it. Right now, your _method field is a delegate of type Func<T>, and you expect that its body contains yet another method which is actually executed. That is a lot to expect from your callers. I would forget about this approach and look for something different.
One way would be to supply a method which takes an array of objects as its parameter (Func<object[], T>), and then invoke it directly with appropriate parameters (but never a method in its body). Even this is less common for a strongly typed language like C# since you lose all type safety (but then again, you do want to be pretty flexible with this framework you are designing).
The other way would be to get a MethodInfo instance, and then use its Invoke method. In a way, this might even express your intents better, because it will be obvious that the executable method is capable of virtually anything.
Next, you could use generics to get some type safety, and require that all your input parameters are wrapped inside a single parameter class. In that case, you might have a strongly typed Func<Tparam, Tresult> method, and your Execute method would accept a Tparam instance as its parameter. This would void the need for any reflection.
[Edit]
As I wrote, I would try to avoid reflection. Since you wrote you basically need a cache of method results, a simple approach might be something like:
Create a wrapper for your list of parameters so that you can compare them "by value". I added an example class, but you might even want to allow passing an IEqualityComparer explicitly, so that you don't have to override Equals for each partial parameter.
// implements `IEquatable` for a list of parameters
class Parameters : IEquatable<Parameters>
{
private readonly object[] _parameters;
public Parameters(object[] parms)
{
_parameters = parms;
}
#region IEquatable<Parameters> Members
public bool Equals(Parameters other)
{
if (other == null)
return false;
if (_parameters.Length != other._parameters.Length)
return false;
// check each parameter to see if it's equal
// ...
}
public override bool Equals(object obj)
{
return Equals(obj as Parameters);
}
public override int GetHashCode()
{ ... }
#endregion
}
Create a cache for a single service. Using the wrapper class above, it should simply check if a cached result exists:
// contains cached results for a single service
class CachedCallInfo
{
private readonly Func<object[], object> _method;
private readonly Dictionary<Parameters, object> _cache
= new Dictionary<Parameters, object>();
public CachedCallInfo(Func<object[], object> method)
{
_method = method;
}
public T GetResult<T>(params object[] parameters)
{
// use out Parameters class to ensure comparison
// by value
var key = new Parameters(parameters);
object result = null;
// result exists?
if (!_cache.TryGetValue(key, out result))
{
// do the actual service call
result = _method(parameters);
// add to cache
_cache.Add(key, result);
}
return (T)result;
}
}
Create the final class which will reference services by name:
public class ServiceCache
{
private readonly Dictionary<string, CachedCallInfo> _services =
new Dictionary<string, CachedCallInfo>();
public void RegisterService(string name, Func<object[], object> method)
{
_services[name] = new CachedCallInfo(method);
}
// "params" keyword is used to simplify method calls
public T GetResult<T>(string serviceName, params object[] parameters)
{
return _services[serviceName].GetResult<T>(parameters);
}
}
Your cache setup will then look like this:
serviceCache.RegisterService("ServiceA", #params => DoSomething(#params));
serviceCache.RegisterService("ServiceB", #params => SomethingElse(#params));
And you would simply call it like this:
var result = serviceCache.GetResult("ServiceA", paramA, paramB, paramC);
Not sure why this is useful, but here goes:
public class SomeCrazyClass<T>
{
private Expression<Func<T>> _method;
public void SetExecutableMethod(Expression<Func<T>> methodParam)
{
_method = methodParam;
}
public object ExecuteMethod(SomeService someService, object[] parameterValues)
{
var methodCallExpression = _method.Body as MethodCallExpression;
var method = methodCallExpression.Method;
var methodCall = Expression.Call(Expression.Constant(someService), method,
parameterValues.Select(Expression.Constant));
return Expression.Lambda(methodCall).Compile().DynamicInvoke();
}
}
Call it like so:
public static void InitAndTest()
{
var something = new SomeCrazyClass<int>(); //or whatever type your method returns
var _service = new SomeService();
something.SetExecutableMethod(() => _service.SomeMethod1("param1 placeholder", "param2 placeholder"));
var result1 = something.ExecuteMethod(_service,new object[] {"Test1", "Test2"});
var result2 = something.ExecuteMethod(_service, new object[] {"Test3", "Test4"});
}
Personally, I think you're going WAY overboard, unless there is an overriding architecture need to deal with the lambda as an expression tree. But, I digress.
Instead of working with the reflective elements (which are basically for description only in terms of an expression tree), look at the Arguments member of your MethodCallExpression. It will contain several ContantExpression objects, which you can replace with your own ConstantExpressions containing the string values you want to pass in. However, Expressions are read-only; you have to rebuild an equivalent tree for this call.
public class FuncManipulator<T>
{
private Func<T> _method;
public void SetExecutableMethod(Func<T> methodParam)
{
_method = methodParam;
}
//you forgot the "params" keyword
public T ExecuteMethod(params object[] parameterValues)
{
//get the number of parameters _method has;
var methodCallExpression = _method.Body as MethodCallExpression;
var arguments = methodCallExpression.Arguments;
var newArguments = new List<Expression>();
for (int i = 0; i < arguments.Count(); i++ )
{
newArguments.Add(Expression.Constant(parameterValues[i]));
}
//"Clone" the expression, specifying the new parameters instead of the old.
var newMethodExpression = Expression.Call(methodCallExpression.Object,
methodCallExpression.Method,
newArguments)
return newMethodExpression.Compile()();
}
}
...
public void InitAndTest()
{
SetExecutableMethod( () => _service.SomeMethod1("param1 placeholder", "param2 placeholder") );
T result1 = ExecuteMethod("Test1", "Test2");
T result2 = ExecuteMethod("Test3", "Test4");
T result3 = ExecuteMethod("Test6", "Test5");
}
This will work as long as the expression tree can find the Func referred to by MethodCallExpression.method within the current instance.
However, I think there's a much simpler way:
public class FuncManipulator<T>
{
private Func<T> _method;
public void SetExecutableMethod(Func<T> methodParam)
{
_method = methodParam;
}
//you must pass the actual array; we are creating a closure reference that will live
//as long as the delegate
public void SetMethodParams(object[] param)
{
_param = param;
}
public T ExecuteMethod(params object[] passedParam)
{
//We have to re-initialize _param based on passedParam
//instead of simply reassigning the reference, because the lambda
//requires we don't change the reference.
for(int i=0; i<_param.Length; i++)
_param[i] = passedParam.Length <= i ? null : passedParam[i];
//notice we don't pass _param; the lambda already knows about it
//via the reference set up when declaring the lambda.
return _method();
}
}
...
public void InitAndTest()
{
//this is an "external closure" we must keep in memory
object[] param = new object[2];
SetExecutableMethod( () => _service.SomeMethod1(param[0], param[1]) );
//We do so by passing the reference to our object
SetMethodParams(param);
//now, don't ever reassign the entire array.
//the ExecuteMethod function will replace indices without redefining the array.
T result1 = ExecuteMethod("Test1", "Test2");
T result2 = ExecuteMethod("Test3", "Test4");
T result3 = ExecuteMethod("Test6", "Test5");
}
How can I get the custom attributes of a method from a Action<T> delegate?
Example:
//simple custom attribute
public class StatusAttribute : Attribute
{
public string Message { get; set; } = string.Empty;
}
// an extension methodto wrap MethodInfo.GetCustomAttributes(Type, Bool) with
// generics for the custom Attribute type
public static class MethodInfoExtentions
{
public static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>(this MethodInfo methodInfo, bool inherit) where TAttribute : Attribute
{
object[] attributeObjects = methodInfo.GetCustomAttributes(typeof(TAttribute), inherit);
return attributeObjects.Cast<TAttribute>();
}
}
// test class with a test method to implment the custom attribute
public class Foo
{
[Status(Message="I'm doing something")]
public void DoSomething()
{
// code would go here
}
}
// creates an action and attempts to get the attribute on the action
private void CallDoSomething()
{
Action<Foo> myAction = new Action<Foo>(m => m.DoSomething());
IEnumerable<StatusAttribute> statusAttributes = myAction.Method.GetCustomAttributes<StatusAttribute>(true);
// Status Attributes count = 0? Why?
}
I realize I could do this by using reflection on Foo, but for what I'm trying to create I have to use an Action<T>.
The problem is that the action doesn't directly point at Foo.DoSomething. It points at a compiler-generated method of the form:
private static void <>__a(Foo m)
{
m.DoSomething();
}
One option here would be to change it to an Expression<Action<T>>, then you can dissect the expression tree afterwards and extract the attributes:
Expression<Action<Foo>> myAction = m => m.DoSomething();
var method = ((MethodCallExpression)myAction.Body).Method;
var statusAttributes = method.GetCustomAttributes<StatusAttribute>(true);
int count = statusAttributes.Count(); // = 1
The issue is that the lambda m => m.DoSomething() is not the same as DoSomething. It is a lambda expression which gets compiled into a method call on a compiler-generated method, possibly using a compiler-generated type (though maybe not the latter, since there are no captured local variables).
A very verbose way of getting an Action<Foo> from an instance (non-static) method of the Foo type is this:
var myAction = (Action<Foo>)Delegate.CreateDelegate(
typeof(Action<Foo>),
null, // treat method as static, even though it's not
typeof(Foo).GetMethod("DoSomething", BindingFlags.Instance | BindingFlags.Public)
);
Obviously, that is far from ideal and probably in fact useless in your case; but it's worth knowing ;)
Update: Actually, it just occurred to me you could write a quick extension method to make this easy for any instance method that you want to wrap as a static method (and maintain the "correct" MethodInfo):
public static class ActionEx
{
public static Action<T> ToStaticMethod<T>(this Action action)
{
if (!(action.Target is T))
{
throw new ArgumentException("Blah blah blah.");
}
return (Action<T>)Delegate.CreateDelegate(
typeof(Action<T>),
null,
action.Method
);
}
}
This would allow you to do:
Action<Foo> myAction = new Action(new Foo().DoSomething).ToStaticMethod<Foo>();
Admittedly, it's not as nice as m => m.DoSomething(); but it does give you an Action<T> whose Method property actually references the DoSomething method directly.
Alternately, instead of an Action<T>, you could use an Expression<Action<T>> and get the MethodInfo from that. Note that the syntax looks just the same in this case:
Action<Foo> myAction = m => m.DoSomething();
Expression<Action<Foo>> myExpression = m => m.DoSomething();
But that is a tricky proposition since an arbitrary Expression<Action<T>> is not guaranteed to be as simple as just m => m.DoSomething().
None of previous answers (except #Marc Gravell♦ 's which has no user's code) seems to be compilable :)
So I would propose mine:
private static void CallDoSomething()
{
var f = new Foo();
Action myAction = f.DoSomething;
IEnumerable<StatusAttribute> statusAttributes = myAction.Method.GetCustomAttributes<StatusAttribute>(true);
}
Consider the following (heavily simplified) code:
public T Function<T>() {
if (typeof(T) == typeof(string)) {
return (T) (object) "hello";
}
...
}
It's kind of absurd to first cast to object, then to T. But the compiler has no way of knowing that the previous test assured T is of type string.
What is the most elegant, idiomatic way of achieving this behavior in C# (which includes getting rid of the stupid typeof(T) == typeof(string), since T is string can't be used)?
Addendum: There is no return type variance in .net, so you can't make a function overload to type string (which, by the way, is just an example, but one reason why association end redefinition in polymorphism, e.g. UML, can't be done in c#). Obviously, the following would be great, but it doesn't work:
public T Function<T>() {
...
}
public string Function<string>() {
return "hello";
}
Concrete Example 1: Because there's been several attacks to the fact that a generic function that tests for specific types isn't generic, I'll try to provide a more complete example. Consider the Type-Square design pattern. Here follows a snippet:
public class Entity {
Dictionary<PropertyType, object> properties;
public T GetTypedProperty<T>(PropertyType p) {
var val = properties[p];
if (typeof(T) == typeof(string) {
(T) (object) p.ToString(this); // magic going here
}
return (T) TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(val);
}
}
Concrete Example 2: Consider the Interpreter design pattern:
public class Expression {
public virtual object Execute() { }
}
public class StringExpression: Expression {
public override string Execute() { } // Error! Type variance not allowed...
}
Now let's use generics in Execute to allow the caller to force a return type:
public class Expression {
public virtual T Execute<T>() {
if(typeof(T) == typeof(string)) { // what happens when I want a string result from a non-string expression?
return (T) (object) do_some_magic_and_return_a_string();
} else if(typeof(T) == typeof(bool)) { // what about bools? any number != 0 should be True. Non-empty lists should be True. Not null should be True
return (T) (object) do_some_magic_and_return_a_bool();
}
}
}
public class StringExpression: Expressiong {
public override T Execute<T>() where T: string {
return (T) string_result;
}
}
If you're making these types of checks in a generic method, I'd rethink your design. The method is obviously not truly generic - if it were, you wouldn't need specific type checking...
Situations like this typically can be handled more cleanly by a redesign. One alternative is often to provide an overload of the appropriate type. Other design alternatives which avoid the type-specific behavior exist, as well, such as Richard Berg's suggestion of passing in a delegate.
using System;
using System.Collections.Generic;
using System.Linq;
namespace SimpleExamples
{
/// <summary>
/// Compiled but not run. Copypasta at your own risk!
/// </summary>
public class Tester
{
public static void Main(string[] args)
{
// Contrived example #1: pushing type-specific functionality up the call stack
var strResult = Example1.Calculate<string>("hello", s => "Could not calculate " + s);
var intResult = Example1.Calculate<int>(1234, i => -1);
// Contrived example #2: overriding default behavior with an alternative that's optimized for a certain type
var list1 = new List<int> { 1, 2, 3 };
var list2 = new int[] { 4, 5, 6 };
Example2<int>.DoSomething(list1, list2);
var list1H = new HashSet<int> { 1, 2, 3 };
Example2<int>.DoSomething<HashSet<int>>(list1H, list2, (l1, l2) => l1.UnionWith(l2));
}
}
public static class Example1
{
public static TParam Calculate<TParam>(TParam param, Func<TParam, TParam> errorMessage)
{
bool success;
var result = CalculateInternal<TParam>(param, out success);
if (success)
return result;
else
return errorMessage(param);
}
private static TParam CalculateInternal<TParam>(TParam param, out bool success)
{
throw new NotImplementedException();
}
}
public static class Example2<T>
{
public static void DoSomething(ICollection<T> list1, IEnumerable<T> list2)
{
Action<ICollection<T>, IEnumerable<T>> genericUnion = (l1, l2) =>
{
foreach (var item in l2)
{
l1.Add(item);
}
l1 = l1.Distinct().ToList();
};
DoSomething<ICollection<T>>(list1, list2, genericUnion);
}
public static void DoSomething<TList>(TList list1, IEnumerable<T> list2, Action<TList, IEnumerable<T>> specializedUnion)
where TList : ICollection<T>
{
/* stuff happens */
specializedUnion(list1, list2);
/* other stuff happens */
}
}
}
/// I confess I don't completely understand what your code was trying to do, here's my best shot
namespace TypeSquarePattern
{
public enum Property
{
A,
B,
C,
}
public class Entity
{
Dictionary<Property, object> properties;
Dictionary<Property, Type> propertyTypes;
public T GetTypedProperty<T>(Property p)
{
var val = properties[p];
var type = propertyTypes[p];
// invoke the cast operator [including user defined casts] between whatever val was stored as, and the appropriate type as
// determined by the domain model [represented here as a simple Dictionary; actual implementation is probably more complex]
val = Convert.ChangeType(val, type);
// now create a strongly-typed object that matches what the caller wanted
return (T)val;
}
}
}
/// Solving this one is a straightforward application of the deferred-execution patterns I demonstrated earlier
namespace InterpreterPattern
{
public class Expression<TResult>
{
protected TResult _value;
private Func<TResult, bool> _tester;
private TResult _fallback;
protected Expression(Func<TResult, bool> tester, TResult fallback)
{
_tester = tester;
_fallback = fallback;
}
public TResult Execute()
{
if (_tester(_value))
return _value;
else
return _fallback;
}
}
public class StringExpression : Expression<string>
{
public StringExpression()
: base(s => string.IsNullOrEmpty(s), "something else")
{ }
}
public class Tuple3Expression<T> : Expression<IList<T>>
{
public Tuple3Expression()
: base(t => t != null && t.Count == 3, new List<T> { default(T), default(T), default(T) })
{ }
}
}
Can you use as here?
T s = "hello" as T;
if(s != null)
return s;
I can't think of an "elegant" way to do this. As you say, the compiler can't know that the conditional has ensured that the type of T is string. As a result, it has to assume that, since there's no generalized way to convert from string to T, it's an error. object to T might succeed, so the compiler allows it.
I'm not sure I'd want an elegant way to express this. Although I can see where it'd be necessary to do explicit type checks like this in some situations, I think I'd want it to be cumbersome because it really is a bit of a hack. And I'd want it to stick out: "Hey! I'm doing something weird here!"
Ok, I took a run at it from several different angles and came up short. I would have to conclude that if your current implementation gets the job done you should take the win and move on. Short of some arcane emissions what you got is what you get.
But the compiler has no way of knowing
that the previous test assured T is of
type string.
Umm.... If I am not mistaken, generics is just code gen. The compiler generates a matching method for each distinct type found in the calling methods. So the compiler does know the type argument for the overload being called. Again; If I am not mistaken.
But overall, i think you are misusing the generic in this case, from what I can see, and as others have stated, there are more appropriate solutions..... which are unnamable unless you post code that completely specifies your requirements.
just my 2 pesos...