I have the following C# class:
public class MyType<T>
{
public void TryParse(string p_value)
{
T value ;
Parser.TryParse(p_value, out value);
// Do something with value
}
}
The point is to call the right Parser.TryParse method, depending on the generic type T.
This uses the following static class:
static public class Parser
{
static public void TryParse(string p_intput, out object p_output)
{
// Do something and return the right value
}
static public void TryParse(string p_intput, out double p_output)
{
// Do something and return the right value
}
static public void TryParse(string p_intput, out int p_output)
{
// Do something and return the right value
}
}
I expected this to work: In the worst case, the "object" TryParse would be called. Instead, I have two compilation errors:
CS1502: The best overloaded method match for 'Parser.TryParse(string, out object)' has some invalid arguments
CS1503: Argument 2: cannot convert from 'out T' to 'out object'
Question 1: I don't understand why this doesn't work: I can be naive, but aren't all C# objects supposed to derive from "object" ? Why T cannot be converted to object?
Question 2: How can I dispatch a method with generic type T into the right non-generic methods (i.e. MyType<T>.TryParse calling the right Parser.TryParse according to the right type of T) ?
Note
The question was edited to reflect the original question intent (as written in the title: How to dispatch C# generic method call into specialized method calls)
Actually, ref and out parameters do not allow type variation. So, to pass a variable to a method expecting an out object parameter, that variable must be declared as object.
From the specification (§10.6.1.2 and §10.6.1.3)
When a formal parameter is a reference parameter, the corresponding argument in a method invocation must consist of the keyword ref followed by a variable-reference (§5.3.3) of the same type as the formal parameter.
When a formal parameter is an output parameter, the corresponding argument in a method invocation must consist of the keyword out followed by a variable-reference (§5.3.3) of the same type as the formal parameter.
See: Why do ref and out parameters not allow type variation? for some insight into why.
Bonus question: How can I dispatch a method with generic type T into the right non-generic methods (i.e. MyType<T>.TryParse calling the right Parser.TryParse according to the right type of T)?
I'm going to turn it back around on you. Why are you doing this? If you are invoking MyType<T>.TryParse as, say, MyType<int>.TryParse, why not call Int32.TryParse directly? What is this extra layer buying you?
I know this is somewhat low-tech, but I have had the same problem, where I solved it by making a Dictionary<Type, Parser> containing the individual parsers. I will be interested in what answers this questions bring.
Regards,
Morten
Current solution
The current solution I use at work is based on dynamic dispatch, that is, the keyword dynamic as defined on C# 4.0.
The code is something like (from memory) :
public class Parser
{
static public void TryParse<T>(string p_input, out T p_output)
{
// Because m_p is dynamic, the function to be called will
// be resolved at runtime, after T is known...
m_p.DoTryParse(p_input, out p_output) ;
}
// The dynamic keyword means every function called through
// m_p will be resolved at runtime, at the moment of the call
private dynamic m_p = new Parser() ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
private void DoTryParse(string p_input, out double p_output)
{ /* Do something and return the right value */ }
private void DoTryParse(string p_input, out int p_output)
{ /* Do something and return the right value */ }
// etc.
private void DoTryParse<T>(string p_input, out T p_output)
{
// fallback method... There are no dedicated method for T,
// so p_output becomes the default value for T
p_output = default(T) ;
}
}
The elegant part is that it can't fail (the fallback function will be called, if none with a better signature match is found), and that it follows a simple pattern (overload the function).
Of course, the real-life, production code is somewhat different, and more complicated because, with but one public static method, I want to :
parse both reference objects (classes) and value objects (structs)
parse enums
parse nullable types
I want to offer the user the possibility to derive from Parser to offer its own overloads in addition to the default ones
But I guess the use of dynamic in the current solution is, in the end, the same thing as doing reflection as done in the original answer below. Only the "notation" changes.
Conclusion, I now have the following method :
public class Parser
{
static public void TryParse<T>(string p_input, out T p_output)
{
// etc.
}
}
which is able to parse anything, including in situations where T is not known at compile time (because the code is generic).
Original answer
Jason's answer was right about the first question (about the compiler errors). Still, I had no solution to my problem (dispatching from a generic method to non-generic methods according to the runtime generic type T).
I tried LukeH's answer, but it didn't work: The generic method is always called, no matter what (even when removing the out qualifier of the second parameter).
Morten's answer is the most sane one that should works, but it doesn't make use of reflection.
So, to solve my own problem, I used reflection. This needs the rewriting of the generic TryParse method:
public class MyType<T>
{
public void TryParse(string p_value)
{
T value = default(T);
// search for the method using reflection
System.Reflection.MethodInfo methodInfo = typeof(Parser).GetMethod
(
"TryParse",
new System.Type[] { typeof(string), typeof(T).MakeByRefType() }
);
if (methodInfo != null)
{
// the method does exist, so we can now call it
var parameters = new object[] { p_value, value };
methodInfo.Invoke(null, parameters);
value = (T)parameters[1];
}
else
{
// The method does not exist. Handle that case
}
}
}
I have the source code available if needed.
This problem intrigued me, so I did some research and found a nice thing by Paul Madox. This seems to do the trick.
public static T SafeParseAndAssign<T>(string val) where T: new()
{
try
{
T ValOut = new T();
MethodInfo MI = ValOut.GetType().
GetMethod("Parse", new Type[] { val.GetType() });
return (T)MI.Invoke(ValOut, new object[] { val });
}
catch
{
// swallow exception
}
return default(T);
}
Related
Consider the following code:
public class Tests
{
public void Test()
{
Assert.AreEqual("Int", DoSomething(1));
}
public static string DoSomething<T>(T value)
{
return "Generic";
}
public static string DoSomething(int value)
{
return "Int";
}
}
As expected, the non-generic DoSomething method will be invoked. Now consider the following modification:
public class Tests
{
public void Test()
{
Assert.AreEqual("Int", DoSomething(1));
}
public static string DoSomething<T>(T value)
{
return "Generic";
}
public static string DoSomething<T>(int value)
{
return "Int";
}
}
The only thing I've changed is adding the T type parameter to the second overload, thus making it generic. Note that the type parameter is not used.
That modification causes the first DoSomething method to be called. Why? The compiler has all the information it needs in order to choose the second method.
Can you please explain why, or even better, point me to the section of the C# specification that explains this behavior?
In your call, you're not specifying a type argument - so the compiler would have to infer the type of T. It can't do that for your second method, because the type parameter is never mentioned in the declared parameters. Therefore, that overload is not applicable, and is ignored.
If you specify a type argument to the call, e.g. any of
DoSomething<int>(1)
DoSomething<object>(1)
DoSomething<string>(1)
... then in all cases the second overload will be called.
From section 7.6.5.1 of the C# 5 spec, (method invocations) when constructing the set of candidate methods:
If F is generic and M has no type argument list, F is a candidate when:
Type inference (§7.5.2) succeeds, inferring a list of type arguments for the call, and
Once the inferred type arguments are substituted for the corresponding method type parameters, all constructed types in the parameter list of F satisfy their constraints (§4.4.4), and the parameter list of F is applicable with respect to A (§7.5.3.1).
As type inference doesn't succeed, the second method isn't in the candidate set, so by the time we get to real overload resolution, the set just has a single method in (the first one).
the compiler can not determine the type of pattern in the call DoSomething(1), but if you specify [int] it will be selected another method.
I currently have a switch statement that runs around 300 odd lines. I know this is not as giant as it can get, but I'm sure there's a better way to handle this.
The switch statement takes an Enum that is used to determine certain properties that pertain to logging. Right now the problem sets in that it is very easy to leave out an enumeration value and that it will not be given a value as it is not in the switch statement.
Is there an option one can use to ensure that every enumeration is used and given a custom set of values it needs to do its job?
EDIT:
Code sample as requested: (This is simplistic, but shows exactly what I mean. Also an Enumeration would exist with the below values.)
internal void GenerateStatusLog(LogAction ActionToLog)
{
switch (ActionToLog)
{
case LogAction.None:
{
return;
}
case LogAction.LogThis:
{
ActionText = "Logging this Information";
LogText = "Go for it.";
break;
}
}
// .. Do everything else
}
EDIT
I thought this over again, looked around in related questions in SO, and I wrote some code. I created a class named AdvancedSwitch<T>, which allows you to add cases and exposes a method to evaluate a value and lets you specify values that it should check for existence.
This is what I came up with:
public class AdvancedSwitch<T> where T : struct
{
protected Dictionary<T, Action> handlers = new Dictionary<T, Action>();
public void AddHandler(T caseValue, Action action)
{
handlers.Add(caseValue, action);
}
public void RemoveHandler(T caseValue)
{
handlers.Remove(caseValue);
}
public void ExecuteHandler(T actualValue)
{
ExecuteHandler(actualValue, Enumerable.Empty<T>());
}
public void ExecuteHandler(T actualValue, IEnumerable<T> ensureExistence)
{
foreach (var val in ensureExistence)
if (!handlers.ContainsKey(val))
throw new InvalidOperationException("The case " + val.ToString() + " is not handled.");
handlers[actualValue]();
}
}
You can consume the class this way:
public enum TrafficColor { Red, Yellow, Green }
public static void Main()
{
Console.WriteLine("Choose a traffic color: red, yellow, green?");
var color = (TrafficColor)Enum.Parse(typeof(TrafficColor), Console.ReadLine());
var result = string.Empty;
// Creating the "switch"
var mySwitch = new AdvancedSwitch<TrafficColor>();
// Adding a single case
mySwitch.AddHandler(TrafficColor.Green, delegate
{
result = "You may pass.";
});
// Adding multiple cases with the same action
Action redAndYellowDelegate = delegate
{
result = "You may not pass.";
};
mySwitch.AddHandler(TrafficColor.Red, redAndYellowDelegate);
mySwitch.AddHandler(TrafficColor.Yellow, redAndYellowDelegate);
// Evaluating it
mySwitch.ExecuteHandler(color, (TrafficColor[])Enum.GetValues(typeof(TrafficColor)));
Console.WriteLine(result);
}
With the creative use of anonymous delegates, you can easily add new cases to your "switch block". :)
Not that you can also use lambda expressions, and lambda blocks, eg () => { ... } instead of delegate { ... }.
You can easily use this class instead of the long switch blocks.
Original post:
If you use Visual Studio, always create swich statements with the switch code snippet. Type switch press tab twice, and it auto-generates all the possibilities for you.
Then, add a default case to the end which throws an exception, that way when testing your app you will notice that there is an unhandled case, instantly.
I mean something like this:
switch (something)
{
...
case YourEnum.SomeValue:
...
break;
default:
throw new InvalidOperationException("Default case reached.");
}
Well, there's throwing in the default case... There's no edit / compile time construct other than that.
However Strategy, Visitor and other patterns related to them may be appropriate if you choose to do it at run time.
Sample code will help with getting the best answer.
EDIT: Thanks for the sample. I still think it needs a bit of fleshing out as you dont cover whether there are some parameters that only apply to some cases etc.
Action is often used as an alias for the Command pattern and the fact that your Enum is called LogAction signifies that each value carries with it a behavior - be that implied (you stick appropriate code in a case) or explicit (in the specific Command hierarchy class).
Thus it looks to me like a usage of the Command pattern is appropriate (though your sample doesnt prove it) - i.e., have a class (potentially a hierarchy using constructor overloads or any other [set of] factory mechanisms) that keeps the state associated with the request along with the specific behaviour. Then, instead of passing an Enum value, create an appropriate LogCommand instance to the logger, which just invokes it (potentially passing a Log Sink 'receptacle' which the Command can log into). Otherwise you're poking random subsets of parameters in different places.
SEEALSO related posts:
C# - Is there a better alternative than this to ‘switch on type’?
Replace giant switch statement with what?
One possible solution is to use a SortedDictionary:
delegate void EnumHandler (args);
SortedDictionary <Enum, EnumHandler> handlers;
constructor
{
handlers = new SortedDictionary <Enum, EnumHandler> ();
fill in handlers
}
void SomeFunction (Enum enum)
{
EnumHandler handler;
if (handlers.TryGetValue (enum, out handler))
{
handler (args);
}
else
{
// not handled, report an error
}
}
This method does allow you to replace the handlers dynamically. You could also use a List as the value part of the dictionary and have multiple handlers for each enum.
Try to use reflection.
Decorate enum options with attributes that holds associated value and return this value.
Create static class of constants and use reflection for mapping enum-option to constant by name
hope this will help
Some times storing the options in a map is a good solution, you can externalize the configuration to a file too, not sure if it applies to your application.
Long code example here, and the final generic code is a little heavy (EDIT have added an extra example that eliminates the need for the angle brackets at the expense of some final flexibility).
One thing that this solution will give you is good performance - not quite as good as a straightforward switch statement, but each case statement becomes a dictionary lookup and method invocation, so still pretty good. The first call will get a performance penalty, however, due to the use of a static generic that reflects on initialisation.
Create an attribute and generic type as follows:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class DynamicSwitchAttribute : Attribute
{
public DynamicSwitchAttribute(Type enumType, params object[] targets)
{ Targets = new HashSet<object>(targets); EnumType = enumType; }
public Type EnumType { get; private set; }
public HashSet<object> Targets { get; private set; }
}
//this builds a cache of methods for a given TTarget type, with a
//signature equal to TAction,
//keyed by values of the type TEnum. All methods are expected to
//be instance methods.
//this code can easily be modified to support static methods instead.
//what would be nice here is if we could enforce a generic constraint
//on TAction : Delegate, but we can't.
public static class DynamicSwitch<TTarget, TEnum, TAction>
{
//our lookup of actions against enum values.
//note: no lock is required on this as it is built when the static
//class is initialised.
private static Dictionary<TEnum, TAction> _actions =
new Dictionary<TEnum, TAction>();
private static MethodInfo _tActionMethod;
private static MethodInfo TActionMethod
{
get
{
if (_tActionMethod == null)
{
//one criticism of this approach might be that validation exceptions
//will be thrown inside a TypeInitializationException.
_tActionMethod = typeof(TAction).GetMethod("Invoke",
BindingFlags.Instance | BindingFlags.Public);
if (_tActionMethod == null)
throw new ArgumentException(/*elided*/);
//verify that the first parameter type is compatible with our
//TTarget type.
var methodParams = _tActionMethod.GetParameters();
if (methodParams.Length == 0)
throw new ArgumentException(/*elided*/);
//now check that the first parameter is compatible with our type TTarget
if (!methodParams[0].ParameterType.IsAssignableFrom(typeof(TTarget)))
throw new ArgumentException(/*elided*/);
}
return _tActionMethod;
}
}
static DynamicSwitch()
{
//examine the type TTarget to extract all public instance methods
//(you can change this to private instance if need be) which have a
//DynamicSwitchAttribute defined.
//we then project the attributes and the method into an anonymous type
var possibleMatchingMethods =
from method in typeof(TTarget).
GetMethods(BindingFlags.Public | BindingFlags.Instance)
let attributes = method.GetCustomAttributes(
typeof(DynamicSwitchAttribute), true).
Cast<DynamicSwitchAttribute>().ToArray()
where attributes!= null && attributes.Length == 1
&& attributes[0].EnumType.Equals(typeof(TEnum))
select new { Method = method, Attribute = attributes[0] };
//create linq expression parameter expressions for each of the
//delegate type's parameters
//these can be re-used for each of the dynamic methods we generate.
ParameterExpression[] paramExprs = TActionMethod.GetParameters().
Select((pinfo, index) =>
Expression.Parameter(
pinfo.ParameterType, pinfo.Name ?? string.Format("arg{0}"))
).ToArray();
//pre-build an array of these parameter expressions that only
//include the actual parameters
//for the method, and not the 'this' parameter.
ParameterExpression[] realParamExprs = paramExprs.Skip(1).ToArray();
//this has to be generated for each target method.
MethodCallExpression methodCall = null;
foreach (var match in possibleMatchingMethods)
{
if (!MethodMatchesAction(match.Method))
continue;
//right, now we're going to use System.Linq.Expressions to build
//a dynamic expression to invoke this method given an instance of TTarget.
methodCall =
Expression.Call(
Expression.Convert(
paramExprs[0], typeof(TTarget)
),
match.Method, realParamExprs);
TAction dynamicDelegate = Expression.
Lambda<TAction>(methodCall, paramExprs).Compile();
//now we have our method, we simply inject it into the dictionary, using
//all the unique TEnum values (from the attribute) as the keys
foreach (var enumValue in match.Attribute.Targets.OfType<TEnum>())
{
if (_actions.ContainsKey(enumValue))
throw new InvalidOperationException(/*elided*/);
_actions[enumValue] = dynamicDelegate;
}
}
}
private static bool MethodMatchesAction(MethodInfo method)
{
//so we want to check that the target method matches our desired
//delegate type (TAction).
//The way this is done is to fetch the delegate type's Invoke
//method (implicitly invoked when you invoke delegate(args)), and
//then we check the return type and parameters types of that
//against the return type and args of the method we've been passed.
//if the target method's return type is equal to or derived from the
//expected delegate's return type, then all is good.
if (!_tActionMethod.ReturnType.IsAssignableFrom(method.ReturnType))
return false;
//now, the parameter lists of the method will not be equal in length,
//as our delegate explicitly includes the 'this' parameter, whereas
//instance methods do not.
var methodParams = method.GetParameters();
var delegateParams = TActionMethod.GetParameters();
for (int i = 0; i < methodParams.Length; i++)
{
if (!methodParams[i].ParameterType.IsAssignableFrom(
delegateParams[i + 1].ParameterType))
return false;
}
return true;
}
public static TAction Resolve(TEnum value)
{
TAction result;
if (!_actions.TryGetValue(value, out result))
throw new ArgumentException("The value is not mapped");
return result;
}
}
Now do this in a Unit Test:
[TestMethod]
public void TestMethod1()
{
Assert.AreEqual(1,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.BlahBlah)(this));
Assert.AreEqual(125,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.Blip)(this));
Assert.AreEqual(125,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.Bop)(this));
}
public enum Blah
{
BlahBlah,
Bloo,
Blip,
Bup,
Bop
}
[DynamicSwitchAttribute(typeof(Blah), Blah.BlahBlah)]
public int Method()
{
return 1;
}
[DynamicSwitchAttribute(typeof(Blah), Blah.Blip, Blah.Bop)]
public int Method2()
{
return 125;
}
So, given a value of TEnum, and your preferred 'action' type (in your code you would appear to be simply returning nothing and modifying the internal state of the class), you simply consult the DynamicSwitch<> class, ask it to resolve a target method, and then invoke it inline (passing the target object on which the method will be invoked as the first parameter).
I'm not really expecting any votes for this - it's a MAD solution to be honest (it does have the advantage of being able to be applied for any enum type, and even discreet values of type int/float/double, as well as supporting any delegate type) - so perhaps it's a bit of a sledgehammer!
EDIT
Once you have a static generic like this, angle-bracket hell ensues - so we want to try and get rid of them. A lot of the time, this is done by type inference on method parameters etc - but we have a problem here that we can't easily infer a delegate's signature without repeating the method call i.e. (args) => return.
However, you seem to require a method that takes no parameters and returns void, so you can close over this behemoth generic by fixing the delegate type to Action, and throw a fluid API into the mix as well (if that's your kind of thing):
public static class ActionSwitch
{
public class SwitchOn<TEnum>
{
private TEnum Value { get; set; }
internal SwitchOn(TEnum value)
{
Value = value;
}
public class Call<TTarget>{
private TEnum Value { get; set; }
private TTarget Target { get; set; }
internal Call(TEnum value, TTarget target)
{
Value = value;
Target = target;
Invoke();
}
internal void Invoke(){
DynamicSwitch<TTarget, TEnum, Action<TTarget>>.Resolve(Value)(Target);
}
}
public Call<TTarget> On<TTarget>(TTarget target)
{
return new Call<TTarget>(Value, target);
}
}
public static SwitchOn<TEnum> Switch<TEnum>(TEnum onValue)
{
return new SwitchOn<TEnum>(onValue);
}
}
Now add this to the test project:
[TestMethod]
public void TestMethod2()
{
//no longer have any angle brackets
ActionSwitch.Switch(Blah.Bup).On(this);
Assert.IsTrue(_actionMethod1Called);
}
private bool _actionMethod1Called;
[DynamicSwitch(typeof(Blah), Blah.Bup)]
public void ActionMethod1()
{
_actionMethod1Called = true;
}
Only issue with this (apart from the complexity of the solution :) ) is that you'd have to re-build this static wrapper type whenever you want to use a new type of target delegate for a dynamic switch elsewhere. You could generate a generic version based on the Action<...> and Func<...> delegates that incorporates TArg1, TArg(n) and TReturn (if Func<>) - but you'd end up writing a lot more code.
Perhaps I'll turn this into an article on my blog and do all of that - if I get the time!
I am working on rewriting my fluent interface for my IoC class library, and when I refactored some code in order to share some common functionality through a base class, I hit upon a snag.
Note: This is something I want to do, not something I have to do. If I have to make do with a different syntax, I will, but if anyone has an idea on how to make my code compile the way I want it, it would be most welcome.
I want some extension methods to be available for a specific base-class, and these methods should be generic, with one generic type, related to an argument to the method, but the methods should also return a specific type related to the particular descendant they're invoked upon.
Better with a code example than the above description methinks.
Here's a simple and complete example of what doesn't work:
using System;
namespace ConsoleApplication16
{
public class ParameterizedRegistrationBase { }
public class ConcreteTypeRegistration : ParameterizedRegistrationBase
{
public void SomethingConcrete() { }
}
public class DelegateRegistration : ParameterizedRegistrationBase
{
public void SomethingDelegated() { }
}
public static class Extensions
{
public static ParameterizedRegistrationBase Parameter<T>(
this ParameterizedRegistrationBase p, string name, T value)
{
return p;
}
}
class Program
{
static void Main(string[] args)
{
ConcreteTypeRegistration ct = new ConcreteTypeRegistration();
ct
.Parameter<int>("age", 20)
.SomethingConcrete(); // <-- this is not available
DelegateRegistration del = new DelegateRegistration();
del
.Parameter<int>("age", 20)
.SomethingDelegated(); // <-- neither is this
}
}
}
If you compile this, you'll get:
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingConcrete' and no extension method 'SomethingConcrete'...
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingDelegated' and no extension method 'SomethingDelegated'...
What I want is for the extension method (Parameter<T>) to be able to be invoked on both ConcreteTypeRegistration and DelegateRegistration, and in both cases the return type should match the type the extension was invoked on.
The problem is as follows:
I would like to write:
ct.Parameter<string>("name", "Lasse")
^------^
notice only one generic argument
but also that Parameter<T> returns an object of the same type it was invoked on, which means:
ct.Parameter<string>("name", "Lasse").SomethingConcrete();
^ ^-------+-------^
| |
+---------------------------------------------+
.SomethingConcrete comes from the object in "ct"
which in this case is of type ConcreteTypeRegistration
Is there any way I can trick the compiler into making this leap for me?
If I add two generic type arguments to the Parameter method, type inference forces me to either provide both, or none, which means this:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
gives me this:
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Which is just as bad.
I can easily restructure the classes, or even make the methods non-extension-methods by introducing them into the hierarchy, but my question is if I can avoid having to duplicate the methods for the two descendants, and in some way declare them only once, for the base class.
Let me rephrase that. Is there a way to change the classes in the first code example above, so that the syntax in the Main-method can be kept, without duplicating the methods in question?
The code will have to be compatible with both C# 3.0 and 4.0.
Edit: The reason I'd rather not leave both generic type arguments to inference is that for some services, I want to specify a parameter value for a constructor parameter that is of one type, but pass in a value that is a descendant. For the moment, matching of specified argument values and the correct constructor to call is done using both the name and the type of the argument.
Let me give an example:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter<Stream>("source", new FileStream(...)))));
^--+---^ ^---+----^
| |
| +- has to be a descendant of Stream
|
+- has to match constructor of FileService
If I leave both to type inference, the parameter type will be FileStream, not Stream.
I wanted to create an extension method that could enumerate over a list of things, and return a list of those things that were of a certain type. It would look like this:
listOfFruits.ThatAre<Banana>().Where(banana => banana.Peel != Color.Black) ...
Sadly, this is not possible. The proposed signature for this extension method would have looked like:
public static IEnumerable<TResult> ThatAre<TSource, TResult>
(this IEnumerable<TSource> source) where TResult : TSource
... and the call to ThatAre<> fails because both type arguments need to be specified, even though TSource may be inferred from the usage.
Following the advice in other answers, I created two functions: one which captures the source, and another which allows callers to express the result:
public static ThatAreWrapper<TSource> That<TSource>
(this IEnumerable<TSource> source)
{
return new ThatAreWrapper<TSource>(source);
}
public class ThatAreWrapper<TSource>
{
private readonly IEnumerable<TSource> SourceCollection;
public ThatAreWrapper(IEnumerable<TSource> source)
{
SourceCollection = source;
}
public IEnumerable<TResult> Are<TResult>() where TResult : TSource
{
foreach (var sourceItem in SourceCollection)
if (sourceItem is TResult) yield return (TResult)sourceItem;
}
}
}
This results in the following calling code:
listOfFruits.That().Are<Banana>().Where(banana => banana.Peel != Color.Black) ...
... which isn't bad.
Notice that because of the generic type constraints, the following code:
listOfFruits.That().Are<Truck>().Where(truck => truck.Horn.IsBroken) ...
will fail to compile at the Are() step, since Trucks are not Fruits. This beats the provided .OfType<> function:
listOfFruits.OfType<Truck>().Where(truck => truck.Horn.IsBroken) ...
This compiles, but always yields zero results and indeed doesn't make any sense to try. It's much nicer to let the compiler help you spot these things.
If you have only two specific types of registration (which seems to be the case in your question), you could simply implement two extension methods:
public static DelegateRegistration Parameter<T>(
this DelegateRegistration p, string name, T value);
public static ConcreteTypeRegistration Parameter<T>(
this ConcreteTypeRegistration p, string name, T value);
Then you wouldn't need to specify the type argument, so the type inference would work in the example you mentioned. Note that you can implement both of the extension methods just by delegation to a single generic extension method with two type parameters (the one in your question).
In general, C# doesn't support anything like o.Foo<int, ?>(..) to infer only the second type parameter (it would be nice feature - F# has it and it's quite useful :-)). You could probably implement a workaround that would allow you to write this (basically, by separating the call into two method calls, to get two places where the type inferrence can be applied):
FooTrick<int>().Apply(); // where Apply is a generic method
Here is a pseudo-code to demonstrate the structure:
// in the original object
FooImmediateWrapper<T> FooTrick<T>() {
return new FooImmediateWrapper<T> { InvokeOn = this; }
}
// in the FooImmediateWrapper<T> class
(...) Apply<R>(arguments) {
this.InvokeOn.Foo<T, R>(arguments);
}
Why don't you specify zero type parameters? Both can be inferred in your sample. If this is not an acceptable solution for you, I'm frequently encountering this problem too and there's no easy way to solve the problem "infer only one type parameter". So I'll go with the duplicate methods.
What about the following:
Use the definition you provide:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
Then cast the parameter so the inference engine gets the right type:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter("source", (Stream)new FileStream(...)))));
I think you need to split the two type parameters between two different expressions; make the explicit one be part of the type of a parameter to the extension method, so inference can then pick it up.
Suppose you declared a wrapper class:
public class TypedValue<TValue>
{
public TypedValue(TValue value)
{
Value = value;
}
public TValue Value { get; private set; }
}
Then your extension method as:
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TypedValue<TValue> value)
where TReg : ParameterizedRegistrationBase
{
// can get at value.Value
return p;
}
}
Plus a simpler overload (the above could in fact call this one):
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TValue value)
where TReg : ParameterizedRegistrationBase
{
return p;
}
}
Now in the simple case where you are happy to infer the parameter value type:
ct.Parameter("name", "Lasse")
But in the case where you need to explicitly state the type, you can do so:
ct.Parameter("list", new TypedValue<IEnumerable<int>>(new List<int>()))
Looks ugly, but hopefully rarer than the simple fully-inferred kind.
Note that you could just have the no-wrapper overload and write:
ct.Parameter("list", (IEnumerable<int>)(new List<int>()))
But that of course has the disadvantage of failing at runtime if you get something wrong. Unfortunately away from my C# compiler right now, so apologies if this is way off.
I would used the solution:
public class JsonDictionary
{
public static readonly Key<int> Foo = new Key<int> { Name = "FOO" };
public static readonly Key<string> Bar = new Key<string> { Name = "BAR" };
IDictionary<string, object> _data;
public JsonDictionary()
{
_data = new Dictionary<string, object>();
}
public void Set<T>(Key<T> key, T obj)
{
_data[key.Name] = obj;
}
public T Get<T>(Key<T> key)
{
return (T)_data[key.Name];
}
public class Key<T>
{
public string Name { get; init; }
}
}
See:
C#: Exposing type safe API over heterogeneous dictionary
I want to make a method:
object Execute()
{
return type.InvokeMember(..);
}
to accept a generic parameter:
T Execute<T>()
{
return Execute() as T;
/* doesn't work:
The type parameter 'T' cannot be used with the 'as' operator because
it does not have a class type constraint nor a 'class' constraint */
// also neither typeof(T), nor T.GetType() are possible
return (T) Execute(); // ok
}
But I think operator as will be very useful: if result type isn't T method will return null, instead of an exception! Is it possible to do?
You need to add
where T : class
to your method declaration, e.g.
T Execute<T>() where T : class
{
By the way, as a suggestion, that generic wrapper doesn't really add much value. The caller can write:
MyClass c = whatever.Execute() as MyClass;
Or if they want to throw on fail:
MyClass c = (MyClass)whatever.Execute();
The generic wrapper method looks like this:
MyClass c = whatever.Execute<MyClass>();
All three versions have to specify exactly the same three entities, just in different orders, so none are any simpler or any more convenient, and yet the generic version hides what is happening, whereas the "raw" versions each make it clear whether there will be a throw or a null.
(This may be irrelevant to you if your example is simplified from your actual code).
You cannot use the as operator with a generic type with no restriction. Since the as operator uses null to represent that it was not of the type, you cannot use it on value types. If you want to use obj as T, T will have to be a reference type.
T Execute<T>() where T : class
{
return Execute() as T;
}
This small piece of code is an exception safe substitution for the as-keyword:
return Execute() is T value ? value : default(T)
It uses the pattern matching feature introduced with C# 7.
Use it, if you don't want to restrict the generic parameter to a reference type
It seems like you are just adding a wrapper method for casting to the type the user wants, thus only adding overhead to the execution. For the user, writing
int result = Execute<int>();
isn't much different from
int result = (int)Execute();
You can use the out modifier to write the result into a variable in the caller's scope, and return a boolean flag to tell whether it succeeded:
bool Execute<T>(out T result) where T : class
{
result = Execute() as T;
return result != null;
}
Is there a chance that Execute() might return a value type? If so, then you need Earwicker's method for class types, and another generic method for value types. Might look like this:
Nullable<T> ExecuteForValueType<T> where T : struct
The logic inside that method would say
object rawResult = Execute();
Then, you'd have to get the type of rawResult and see if it can be assigned to T:
Nullable<T> finalReturnValue = null;
Type theType = rawResult.GetType();
Type tType = typeof(T);
if(tType.IsAssignableFrom(theType))
{
finalReturnValue = tType;
}
return finalReturnValue;
Finally, make your original Execute message figure out which T is has (class or struct type), and call the appropriate implementation.
Note: This is from rough memory. I did this about a year ago and probably don't remember every detail. Still, I hope pointing you in the general direction helps.
My question concerns c# and how to access Static members ... Well I don't really know how to explain it (which kind of is bad for a question isn't it?) I will just give you some sample code:
Class test<T>{
int method1(Obj Parameter1){
//in here I want to do something which I would explain as
T.TryParse(Parameter1);
//my problem is that it does not work ... I get an error.
//just to explain: if I declare test<int> (with type Integer)
//I want my sample code to call int.TryParse(). If it were String
//it should have been String.TryParse()
}
}
So thank you guys for your answers (By the way the question is: how would I solve this problem without getting an error). This probably quite an easy question for you!
Edit: Thank you all for your answers!
Though I think the try - catch phrase is the most elegant, I know from my experience with vb that it can really be a bummer. I used it once and it took about 30 minutes to run a program, which later on only took 2 minutes to compute just because I avoided try - catch.
This is why I chose the switch statement as the best answer. It makes the code more complicated but on the other hand I imagine it to be relatively fast and relatively easy to read. (Though I still think there should be a more elegant way ... maybe in the next language I learn)
Though if you have some other suggestion I am still waiting (and willing to participate)
The problem is that TryParse isn't defined on an interface or base class anywhere, so you can't make an assumption that the type passed into your class will have that function. Unless you can contrain T in some way, you'll run into this a lot.
Constraints on Type Parameters
Short answer, you can't.
Long answer, you can cheat:
public class Example
{
internal static class Support
{
private delegate bool GenericParser<T>(string s, out T o);
private static Dictionary<Type, object> parsers =
MakeStandardParsers();
private static Dictionary<Type, object> MakeStandardParsers()
{
Dictionary<Type, object> d = new Dictionary<Type, object>();
// You need to add an entry for every type you want to cope with.
d[typeof(int)] = new GenericParser<int>(int.TryParse);
d[typeof(long)] = new GenericParser<long>(long.TryParse);
d[typeof(float)] = new GenericParser<float>(float.TryParse);
return d;
}
public static bool TryParse<T>(string s, out T result)
{
return ((GenericParser<T>)parsers[typeof(T)])(s, out result);
}
}
public class Test<T>
{
public static T method1(string s)
{
T value;
bool success = Support.TryParse(s, out value);
return value;
}
}
public static void Main()
{
Console.WriteLine(Test<int>.method1("23"));
Console.WriteLine(Test<float>.method1("23.4"));
Console.WriteLine(Test<long>.method1("99999999999999"));
Console.ReadLine();
}
}
I made a static dictionary holding a delegate for the TryParse method of every type I might want to use. I then wrote a generic method to look up the dictionary and pass on the call to the appropriate delegate. Since every delegate has a different type, I just store them as object references and cast them back to the appropriate generic type when I retrieve them. Note that for the sake of a simple example I have omitted error checking, such as to check whether we have an entry in the dictionary for the given type.
To access a member of a specific class or interface you need to use the Where keyword and specify the interface or base class that has the method.
In the above instance TryParse does not come from an interface or base class, so what you are trying to do above is not possible. Best just use Convert.ChangeType and a try/catch statement.
class test<T>
{
T Method(object P)
{
try {
return (T)Convert.ChangeType(P, typeof(T));
} catch(Exception e) {
return null;
}
}
}
One more way to do it, this time some reflection in the mix:
static class Parser
{
public static bool TryParse<TType>( string str, out TType x )
{
// Get the type on that TryParse shall be called
Type objType = typeof( TType );
// Enumerate the methods of TType
foreach( MethodInfo mi in objType.GetMethods() )
{
if( mi.Name == "TryParse" )
{
// We found a TryParse method, check for the 2-parameter-signature
ParameterInfo[] pi = mi.GetParameters();
if( pi.Length == 2 ) // Find TryParse( String, TType )
{
// Build a parameter list for the call
object[] paramList = new object[2] { str, default( TType ) };
// Invoke the static method
object ret = objType.InvokeMember( "TryParse", BindingFlags.InvokeMethod, null, null, paramList );
// Get the output value from the parameter list
x = (TType)paramList[1];
return (bool)ret;
}
}
}
// Maybe we should throw an exception here, because we were unable to find the TryParse
// method; this is not just a unable-to-parse error.
x = default( TType );
return false;
}
}
The next step would be trying to implement
public static TRet CallStaticMethod<TRet>( object obj, string methodName, params object[] args );
With full parameter type matching etc.
This isn't really a solution, but in certain scenarios it could be a good alternative: We can pass an additional delegate to the generic method.
To clarify what I mean, let's use an example. Let's say we have some generic factory method, that should create an instance of T, and we want it to then call another method, for notification or additional initialization.
Consider the following simple class:
public class Example
{
// ...
public static void PostInitCallback(Example example)
{
// Do something with the object...
}
}
And the following static method:
public static T CreateAndInit<T>() where T : new()
{
var t = new T();
// Some initialization code...
return t;
}
So right now we would have to do:
var example = CreateAndInit<Example>();
Example.PostInitCallback(example);
However, we could change our method to take an additional delegate:
public delegate void PostInitCallback<T>(T t);
public static T CreateAndInit<T>(PostInitCallback<T> callback) where T : new()
{
var t = new T();
// Some initialization code...
callback(t);
return t;
}
And now we can change the call to:
var example = CreateAndInit<Example>(Example.PostInitCallback);
Obviously this is only useful in very specific scenarios. But this is the cleanest solution in the sense that we get compile time safety, there is no "hacking" involved, and the code is dead simple.
Do you mean to do something like this:
Class test<T>
{
T method1(object Parameter1){
if( Parameter1 is T )
{
T value = (T) Parameter1;
//do something with value
return value;
}
else
{
//Parameter1 is not a T
return default(T); //or throw exception
}
}
}
Unfortunately you can't check for the TryParse pattern as it is static - which unfortunately means that it isn't particularly well suited to generics.
The only way to do exactly what you're looking for would be to use reflection to check if the method exists for T.
Another option is to ensure that the object you send in is a convertible object by restraining the type to IConvertible (all primitive types implement IConvertible). This would allow you to convert your parameter to the given type very flexibly.
Class test<T>
{
int method1(IConvertible Parameter1){
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
}
}
You could also do a variation on this by using an 'object' type instead like you had originally.
Class test<T>
{
int method1(object Parameter1){
if(Parameter1 is IConvertible) {
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
} else {
// Do something else
}
}
}
Ok guys: Thanks for all the fish. Now with your answers and my research (especially the article on limiting generic types to primitives) I will present you my solution.
Class a<T>{
private void checkWetherTypeIsOK()
{
if (T is int || T is float //|| ... any other types you want to be allowed){
return true;
}
else {
throw new exception();
}
}
public static a(){
ccheckWetherTypeIsOK();
}
}
You probably cant do it.
First of all if it should be possible you would need a tighter bound on T so the typechecker could be sure that all possible substitutions for T actually had a static method called TryParse.
You may want to read my previous post on limiting generic types to primitives. This may give you some pointers in limiting the type that can be passed to the generic (since TypeParse is obviously only available to a set number of primitives ( string.TryParse obviously being the exception, which doesn't make sense).
Once you have more of a handle on the type, you can then work on trying to parse it. You may need a bit of an ugly switch in there (to call the correct TryParse ) but I think you can achieve the desired functionality.
If you need me to explain any of the above further, then please ask :)
Best code: restrict T to ValueType this way:
class test1<T> where T: struct
A "struct" here means a value type.
String is a class, not a value type.
int, float, Enums are all value types.
btw the compiler does not accept to call static methods or access static members on 'type parameters' like in the following example which will not compile :(
class MyStatic { public static int MyValue=0; }
class Test<T> where T: MyStatic
{
public void TheTest() { T.MyValue++; }
}
=> Error 1 'T' is a 'type parameter', which is not valid in the given context
SL.
That is not how statics work. You have to think of statics as sort of in a Global class even if they are are spread across a whole bunch of types. My recommendation is to make it a property inside the T instance that can access the necessary static method.
Also T is an actual instance of something, and just like any other instance you are not able to access the statics for that type, through the instantiated value. Here is an example of what to do:
class a {
static StaticMethod1 ()
virtual Method1 ()
}
class b : a {
override Method1 () return StaticMethod1()
}
class c : a {
override Method1 () return "XYZ"
}
class generic<T>
where T : a {
void DoSomething () T.Method1()
}