I'm taking my first steps in c # & asp.net and I'm enjoying it much.
Now, I have a question...
Is there a function in C# to call a class/method as in php?
For example:
$class = array(
"foo", // class name
"bar" // method name
);
$params = array(
"one",
"two"
);
call_user_func_array($class, $params); //execute Foo->bar("one","two");
Nope, there is nothing built in to do exactly that. You could build a method that does something similar using reflection, but it seems like a solution looking for a problem.
void Main()
{
CallUserFuncArray("UserQuery+Foo", "Bar", "One", "Two");
}
// Define other methods and classes here
public class Foo
{
public static void Bar(string a, string b){}
}
public void CallUserFuncArray(string className, string methodName, params object[] args)
{
Type.GetType(className).GetMethod(methodName).Invoke(null, args);
}
As others have noted, there are multiple ways to simulate this, but no "baked-in" functionality in C#. The most flexible way is with reflection, but you can do it in a much simpler (and easier to deal with) way if you know the list of methods you'll be calling beforehand.
class Foo
{
public static string FooA(int p1, int p2)
{
return "FooA:" + p1 + p2;
}
public static string FooB(int p1, int p2) { return "FooB:" + p1 + p2; }
public static string FooC(int p1, int p2) { return "FooC:" + p1 + p2; }
}
class Bar
{
//You can use Func<int, int, object> instead of a delegate type,
//but this way is a little easier to read.
public delegate string Del(int p1, int p2);
public static string DoStuff()
{
var classes = new Dictionary<string, Dictionary<string, Del>>();
classes.Add("Foo", new Dictionary<string, Del>());
classes["Foo"].Add("FooA", Foo.FooA);
classes["Foo"].Add("FooB", Foo.FooB);
classes["Foo"].Add("FooC", Foo.FooC);
//...snip...
return classes["Foo"]["FooA"](5, 7);
}
}
Which, by the way, does work.
If you don't know which methods you want to make available this way, I suggest you reconsider whaever you're trying to do. The only reason I can think of for using strings to choose your execution path would be if you were planning to get those strings from the user. Not only is it a huge no-no to expose inner details of your application like this, but it comes dangerously close to eval-type functionality. There's a reason C# doesn't have an eval method, and it isn't because the designers forgot to put it in.
As #StriplingWarrior said, there's no built-in equivalent of call_user_func_array, but you can do something like it with Reflection.
The problem is that Reflection code can get very complicated very quickly, and can be brittle and error-prone if you're not VERY careful.
For example the following function does what you want:
public static void CallUserFuncArray(string[] func, params string[] args)
{
var type = Type.GetType(func[0]);
if (type == null)
{
throw new ArgumentException("The specified Class could not be found");
}
var method = type.GetMethod(func[1], BindingFlags.Static | BindingFlags.Public);
if (method== null)
{
throw new ArgumentException("The specified Method could not be found");
}
method.Invoke(null, args);
}
You call it like this:
var func = new [] { "Foo", "Bar" };
var args = new [] { "one", "two" };
CallUserFuncArray(func, args);
The problems though are many.
The code only works if Bar is a public static method.
There's a whole new layer of complexity if you need to call an instance method on an object.
The code will explode if the parameters in the args array aren't just right for the target method.
There's no support here for calling methods that expect anything other than string parameters. It's possible to query the type of the arguments expected by the method and convert the types before calling 'Invoke', but you're getting even more messy.
There are many more edge cases that blow out the complexity of this code even more if you need to cater for them.
To paraphrase Carl Franklin (of dotNetRocks fame):
I had a problem I needed to solve, so I used Reflection. Now I have two problems.
I you find yourself need to do this sort of thing thenyou probably need to rethink your overall design.
Related
I have a series of functions that I want to have the following functionality.
When the function is called, add itself to a list of functions remembering the parameters and values
Allow the list of functions to be called at a later date
The different functions have a variety of different parameters and I'm struggling to think of an elegant way to do this. Any help would be appreciated.
I think this would meet your needs, however the functions are not "adding themselves".
public class Recorder
{
private IList<Action> _recording;
public Recorder()
{
_recording = new List<Action>();
}
public void CallAndRecord(Action action)
{
_recording.Add(action);
action();
}
public void Playback()
{
foreach(var action in _recording)
{
action();
}
}
}
//usage
var recorder = new Recorder();
//calls the functions the first time, and records the order, function, and args
recorder.CallAndRecord(()=>Foo(1,2,4));
recorder.CallAndRecord(()=>Bar(6));
recorder.CallAndRecord(()=>Foo2("hello"));
recorder.CallAndRecord(()=>Bar2(0,11,true));
//plays everything back
recorder.Playback();
One way to make the functions "add themselves" would be to use an AOP lib such as postsharp or linfu dynamic proxy, and add an interceptor which adds the function and args to the array. To do this would probably be more work than it would be worth IMO, as the above is much simpler and still achieves the desired functionality.
There's hardly an elegant solution to this. Since you said the methods would all have different signature, there's no way to store them in a single array as delegates. With that out of the way, next you can try is using reflection, storing each parameter value in object[], storing the method as MethodInfo, and then invoking it.
Edit: This is what I could come up with:
private Dictionary<MethodBase, object[]> methodCollection = new Dictionary<MethodBase, object[]>();
public void AddMethod(MethodBase method, params object[] arguments)
{
methodCollection.Add(method, arguments);
}
private void MyMethod(int p1, string p2, bool p3)
{
AddMethod(System.Reflection.MethodInfo.GetCurrentMethod(), new object[] { p1, p2, p3 });
}
private void MyOtherMethod()
{
AddMethod(System.Reflection.MethodInfo.GetCurrentMethod(), new object[] { });
}
Then just invoke with method.Invoke(method.ReflectedType, args)
Maybe you could some how use the Delegate.DynamicInvoke(Object[] obj) function. You could add each method to an object array, then loop through the array calling DynamicInvoke on each one.
I'm not sure I understand your question, but I think you could use array of pointers to a functions(in C# it is called delegates). So when function is called, put function pointer in a list. In this way you can call function from list. Here is some idea. Notice when you add new delegate pointer to a list (functionPointers), in second list myParameters you add new object of type Parameters which holds function parameters in public attribute called parameters. This means that delegate i in list functionPointers for parameters has i-th object in list myParameters. This is how you know which parameters, are for which function. Probably there are some betters solutions, but this is alternative.
delegate void NewDelegate();
class Parameter{
public ArrayList parameters;
}
ArrayList functionPointers=new ArrayList();
ArrayList<Parameter> myParameters=new ArrayList<Parameter>();
NewDelegate myDelegate;
void someFunction(int a, int b){
myDelegate+=someFunction;//you add this function to delegate because this function is called
functionPointers.add(myDelegate);//Add delegete to list
Parameter p=new Parameter();//Create new Parameter object
p.parameters.add(a);//Add function parameters
p.parameters.add(b);
myParameters.add(p);//add object p to myParameters list
}
You could consider using a list of actions or functions
using System;
using System.Collections.Generic;
namespace ReplayConsole
{
class Program
{
private static IList<Action> _actions;
static void Main(string[] args)
{
_actions = new List<Action>
{
() => {
//do thing
},
() => {
//do thing
},
() => {
//do thing
},
() => {
//do thing
},
};
foreach (var action in _actions)
{
action();
}
}
}
if you want to store parameters as well and have you could use a Func and store and use it in much the same way
You could also look at Tasks
EDIT:
looking at the answers that popped up while I was writing mine this solution is very similar to Brook's
I am working on my c# .net application and use implement IoC/DI pattern using Ninject, Now Ninject has a class named ConstructorArgument which takes two arguments(argName,argValue).
So i need to pass static argName something like this
new ConstructorArgument("strVar","")
passing hardcoded string does not seems like a good option.
So i want to create something like dynamics enums using reflection for the constructor arguments, so i dont need to pass hardcoded strings.
Please guide me through this process or suggest me something else to achieve this.
like dynamics enums
There is no such construct readily available. If you really hate the strings, you could write some kind of expression-tree lambda (i.e. () => new Foo(strVal: "") or () => new Foo(""), however - that a: is a lot of work, and b: won't work well if there are other parameters being provided by the container.
To be honest, this is a bit of a non-issue, especially since named arguments mean that parameter names should be treated as a contract. IMO, just use the string. If it worries you, make sure you cover the scenario in a unit test, so that you find out early if it changes.
I agree with #Mark Gravell's stance, except that obfuscators can rename parameters for non-public ctors so the advice doesn't apply in that specific case, so in some cases, you need to whack on a [Obfuscation] on the parameter to preserve the name in some instances.
But I have built nonsense like this which would answer your question. Please don't use it as I regret writing it!
static class StaticReflection<TClass>
{
static string PublicConstructorParameterName<TParameter>()
{
return typeof( TClass ).GetConstructors( BindingFlags.Public | BindingFlags.Instance ).Single().GetParameters().Where( param => param.ParameterType == typeof( TParameter ) ).Single().Name;
}
internal static ConstructorArgument CreateConstructorArgument<TParameter>( TParameter value )
{
return new ConstructorArgument( PublicConstructorParameterName<TParameter>(), value );
}
internal static ConstructorArgument CreateConstructorArgument<TParameter>( Func<IContext, TParameter> argumentResolver )
{
return new ConstructorArgument( PublicConstructorParameterName<TParameter>(), context => (object)argumentResolver( context ) );
}
}
Which works like this:
public class StaticReflectionFacts
{
public class X2
{
}
public class X
{
public X( object param1, X2 param2 )
{
}
}
[Fact]
static void DeriveNinjectConstructorArgumentFromPublic()
{
var newArg = StaticReflection<X>.CreateConstructorArgument( new X2() );
Assert.Equal( "param2", newArg.Name );
}
}
I have imlemented this:
public string GiveConstuctorArgumentName(Type class, Type constructorArgument)
{
var cons = class.GetConstructors();
foreach (var constructorInfo in cons)
{
foreach (var consParameter in constructorInfo.GetParameters())
{
if (consParameter.ParameterType == constructorArgument)
{
return consParameter.Name;
}
}
}
throw new InstanceNotFoundException();
}
Its without LINQ, but its a good start point to understand how its work.
Is there any way to do something like this in C#?
public void DoSomething(string parameterA, int parameterB)
{
}
var parameters = ("someValue", 5);
DoSomething(parameters);
Close, but unfortuantely only using object (so you get lots of boxing/unboxing)
public void DoSomething(params object[] parameters)
{
}
var parameters = new object[]{"someValue", 5};
DoSomething(parameters); // this way works
DoSomething("someValue", 5); // so does this way
Not today, no. We are at present prototyping exactly that feature for a possible hypothetical future version of C#.
If you can provide a really awesome reason why you want this feature, that would be points towards actually getting it out of prototyping and into a possible hypothetical future release. What's your awesome scenario that motivates this feature?
(Remember, Eric's speculations about possible hypothetical future releases of C# are for entertainment purposes only and are not to be construed as promises that there ever will be such a release or that it will have any particular feature set.)
No need to use reflection if you first store as a delegate, but it does require a strong declaration of the delegate.
public void DoSomething(string parameterA, int parameterB)
{
Console.WriteLine(parameterA+" : "+parameterB);
}
void Main()
{
var parameters = new object[]{"someValue", 5};
Action<string,int> func=DoSomething;
func.DynamicInvoke(parameters);
}
...and you can forget about compile-time type/sanity checking of the parameter list. Probably a bad thing.
You can invoke it through reflection, but that'll incur some overhead:
using System;
using System.Reflection;
namespace SO2744885
{
class Program
{
public void DoSomething(string parameterA, int parameterB)
{
Console.Out.WriteLine(parameterA + ": " + parameterB);
}
static void Main(string[] args)
{
var parameters = new object[] { "someValue", 5 };
Program p = new Program();
MethodInfo mi = typeof(Program).GetMethod("DoSomething");
mi.Invoke(p, parameters);
}
}
}
Of course, if you can change the method signature to take an array, that'll work as well, but that will look worse in my opinion.
nope - this is not possible.
Maybe this way is more "clean":
// standard method calling
DoSomething( "Johny", 5 );
// since C# 4.0 you can used "named parameters"
DoSomething( name: "Johny", number: 5 );
// calling with parameter's "container"
DoSomething( new DoSomethingParameters( "Johny", 5 ) );
// calling with parameter's "container"
DoSomething( new DoSomethingParameters{ Name = "Johny", Number = 5 } );
// calling with callback for parameters initialization
DoSomething( p => { p.Name = "Johny"; p.Number = 5; } );
// overload of DoSomething method with callback, which initialize parameters
public void DoSomething( Action<DoSomethingParameters> init ) {
var p = new DoSomethingParameters();
init( p );
DoSomething( p );
}
// overload of DoSomething method for calling with simple parameters
public void DoSomething( string name, int number ) {
var p = new DoSomethingParameters( name, number );
DoSomething( p );
}
// the "main executive" method which is "doing the work"
// all posible parameters are specified as members of DoSomethingParameters object
public void DoSomething( DoSomethingParameters p ) { /* ... */ }
// specify all parameters for DoSomething method
public class DoSomethingParameters {
public string Name;
public int Number;
public DoSomethingParameters() { }
public DoSomethingParameters( string name, int number ) {
this.Name = name;
this.Number = number;
}
}
Inspired by Steven's answer:
static public void Execute<T1, T2>(this Tuple<T1, T2> parameters, Action<T1, T2> action)
{
action(parameters.Item1, parameters.Item2);
}
var parameters = Tuple.Create("someValue", 5);
parameters.Execute(DoSomething);
I like Henrik's answer, except that it imposes a somewhat weird syntax: parameters call a method on themselves. I would do it the other way around. Only problem with this approach is that it makes you explicitly cast a method to a delegate.
Anyway, here's the basic idea:
// wrapped code to prevent horizontal overflow
public static void Execute<T1, T2>
(this Action<T1, T2> action, Tuple<T1, T2> parameters) {
action(parameters.Item1, parameters.Item2);
}
And so on (for more Ts).
Usage:
var parameters = Tuple.Create("Hi", 10);
Action<string, int> action = DoSomething;
action.Execute(parameters);
You can also easily do this with a return value:
// wrapped code to prevent horizontal overflow
public static TResult Return<T1, T2, TResult>
(this Func<T1, T2, TResult> func, Tuple<T1, T2> parameters) {
return func(parameters.Item1, parameters.Item2);
}
And so on.
I'd also like to point out that just because you aren't on .NET 4.0, that doesn't mean you can't easily implement your own Tuple<T1, T2, ...> type.
you can do:
public void DoSomething(string parameterA, int parameterB)
{
}
var func = (Action)(() => DoSomething("someValue", 5));
func();
You can do this (.NET 4.0):
var parameters = Tuple.Create("someValue", 5);
DoSomething(parameters.Item1, parameter.Item2);
If they're all the same type, yes, you can do something to this effect:
public void Print(params string[] args) {
foreach (string arg in args) {
Console.WriteLine(arg);
}
}
// ...
Print("apple", "banana");
Print("apple", "banana", "cherry");
Print("apple", "banana", "cherry", "doughnut");
Otherwise, no, you can't expand parameters in place like that without using reflection. C# doesn't have the equivalent of Ruby's splat operator.
If you don't want to change the method signature why not declare a new method with the appropriate signature and use that as a proxy. Like
public void DoSomething(string parameterA, int parameterB)
{
// Original do Something
}
public void DoSomething(object[] parameters)
{
// some contract check whether the parameters array has actually a good signature
DoSomething(parameters[0] as string,(parameters[1] as int?).Value);
}
var parameters = new object[]{"someValue", 5};
DoSomething(parameters);
You can also try out some of the stuff LinFu.Reflection provides, like Late Binding. With it you can do something like this:
var dosomethingobject = new ObjectThatHasTheDoSomething();
DynamicObject dynamic = new DynamicObject(dosomethingobject);
var parameters = new object[]{"someValue", 5};
dynamic.Methods["DoSomething"](parameters);
For this you need that the DoSomething method is inside an object.
"var" just represents a particular type, it's effectively shorthand for writing a type name. In the above you're not specifying any type. The only way to do this is to make a parameter class to represent the inputs in bulk...
public void DoSomething(Parameters param)
{
...
}
var param = new Parameters("someValue", 5);
DoSomething(param);
...but this is only going to be useful in specific circumstances. You could make multiple Parameters constructors to represent different arrangements of parameters, but the function you're calling will only take ONE input - the Parameters object. So with this you're really undermining the ability to overload a function.
So, in short, no. =)
How about this in .NET 4 (for the sake of curiosity)
public void DoSomething(string parameterA, int parameterB)
{
}
public void Helper(dynamic parameter)
{
DoSomething(parameter.Parameter1, parameter.Parameter2);
}
var parameters = new {Parameter1="lifeUniverseEverything", Parameter2=42};
Helper(parameters);
This question already has answers here:
Closed 13 years ago.
Duplicate of What is the "< >" syntax within C#
Actually i want to know 'why and when should i use generics?'.
What is the need for it?
Generics are a way of ensuring Type Safety at Compile time in C#.
Example- Pre-Generics:
class Person
{
string name;
string lastname;
public Person(string _name ) { this.name = _name; }
}
class ClientCode
{
public static void Main()
{
//create a list of person
ArrayList personList = new ArrayList();
Person p1 = new Person("John");
Person p2 = new Person("Ram");
personList.Add(p1);
personList.Add(p2);
// BUT, someone can do something like:
// ArrayList does not stop adding another type of object into it
object q = new object();
personList.Add(q);
// while accessing personlist
foreach(object obj in personlist)
{
Person p = obj as Person;
// do something, for person
// But it will fail for last item in list 'q' since its is not person.
}
}
}
Example- Post-Generics:
class ClientCode
{
public static void Main()
{
//create a list of person
List<Person> personList = new List<Person>();
Person p1 = new Person("John");
Person p2 = new Person("Ram");
personList.Add(p1);
personList.Add(p2);
// Someone can not add any other object then Person into personlist
object q = new object();
personList.Add(q); // Compile Error.
// while accessing personlist, No NEED for TYPE Casting
foreach(Person obj in personlist)
{
// do something, for person
}
}
}
Generics let you parameterize code over types in the same way that arguments let you parameterize it over values. That probably doesn't explain a whole lot, so lets go through it a step at a time:
Imagine you want a program to print "I like bunnies". You write this:
static void Main()
{
ILikeBunnies();
}
void ILikeBunnies() { Console.WriteLine("I like bunnies"); }
All well and good. But you also like cheese, so now you have:
static void Main()
{
ILikeBunnies();
ILikeCheese();
}
void ILikeBunnies() { Console.WriteLine("I like bunnies"); }
void ILikeCheese() { Console.WriteLine("I like cheese"); }
You notice that your two functions are almost identical. You want to reuse the same function, but provide different values for what you like:
static void Main()
{
ILike("bunnies");
ILike("cheese");
}
void ILike(string what) { Console.WriteLine("I like " + what); }
This is what function arguments are for: they let you reuse the same code with different values.
Generics are like that, but instead of passing in different values, you pass in types. Lets say you've got code that needs to bundle two strings into an array:
static void Main()
{
string[] s = Pair("a", "b");
}
string[] Pair(string a, string b) { return new string[] { a, b }; }
Fine and dandy. Later you realize you also need to bundle ints into an array:
static void Main()
{
string[] s = Pair("a", "b");
int[] i = Pair(1, 2);
}
string[] Pair(string a, string b) { return new string[] { a, b }; }
int[] Pair(int a, int b) { return new int[] { a, b }; }
Just like before, we can see there's a bunch of redundancy there. What we need is a function that returns a pair of whatever and a way to pass in the type of what we want a pair of. This is what generics are for:
static void Main()
{
string[] s = Pair<string>("a", "b");
int[] i = Pair<int>(1, 2);
}
T[] Pair<T>(T a, T b) { return new T[] { a, b }; }
The angle brackets let you pass in a type to a function in the same way parentheses let you pass in values. "T" here is the name of a type argument just like "what" was the value argument above. Any place T appears in the function will be replaced with the actual type you pass in (string and int in the example).
There's a bunch of stuff you can do with generics beyond this, but that's the basic idea: generics let you pass types into functions (and classes) in the same way arguments let you pass in values.
Generics basically remove the need to cast and objects into their base type.
e.g. if you want to store a group of Foos in a List.
You used to have to either create your owen FooList or cast the item as objects.
All this takes you time and the complier.
With Generics all you have to do is sat List it checks you types and speeds up you programs. (no boxing and unboxing)
Suppose you yourself is an algorithm which can sort whatever objects that can be compared pair-wise (playing-cards, CDs, business cards, whatever). You're not actually interested in what these concrete objects are provided you can compare them. Thus you become a generic (here "generic" is used in a broad term, not in C# sense) algorithm.
Generics in .NET help facilitate this particular kind of behavior not only in terms of algorithms (generic functions), but also in terms of generic types (classes, structs, delegates, interfaces).
Just to add to what everyone else will tell you, more practically, try doing something with an ArrayList or System.Array object and then try doing it with a List<T> and you can immediately see the how generics allows you to write more readable code and write it quicker too.
I blogged about it a long time ago, here. I was working with XML, and I wanted a helper that would get an XmlElement or an XmlAttribute (based on an XPath) and let me work with it. It was a nice simple example I worked through in the real world when generics were fairly new to C#.
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()
}