How to use generics to pass argument to a non-generic method? - c#

Why does the following code not compile?
How can I create a generic method which calls the appropriate "BitConverter.GetBytes" overload based on if the generic type is an "int", "bool", "char", etc.?
More generally, how can I create a generic method which calls a non-generic method based on the generic parameter's type?
using System;
public class Test
{
public static void Main()
{
var f = new Foo();
f.GetBytes(10); // should call BitConverter.GetBytes(int);
f.GetBytes(true); // should call BitConverter.GetBytes(bool);
f.GetBytes('A'); // should call BitConverter.GetBytes(char);
}
}
public class Foo
{
public byte[] GetBytes <TSource> (TSource input)
{
BitConverter.GetBytes(input);
}
}

More generally, how can I create a generic method which calls a non-generic method based on the generic parameter's type?
In general, you can't, unless the method in question takes System.Object as a parameter. The problem is that the generic isn't constrained to just types that would be allowed by the method call arguments.
The closest you can do is to use runtime binding:
public byte[] GetBytes <TSource> (TSource input)
{
dynamic obj = input;
BitConverter.GetBytes(obj);
}
This pushes the method binding logic to runtime, and will throw if there isn't an appropriate method to call.

The reason this doesn't work is that generic methods still resolve calls to methods made within them statically. Since TSource could be any type at all, it can only call a method on BitConverter which takes an object argument. Since none exists, the compilation fails.
The only way to get the behaviour you want to is to use dynamic:
public byte[] GetBytes <TSource> (TSource input)
{
BitConverter.GetBytes((dynamic)input);
}
although the generic parameter is now redundant and you have no type safety.
In this situation you can either create a number of matching overloads e.g.
public byte[] GetBytes(bool b) { ... }
public byte[] GetBytes(int i) { ... }
or take a Func<T, byte[]> argument and wrap each BitConverter method you need e.g.
public void DoSomething<T>(T input, Func<T, byte[]> f)
{
byte[] bytes = f(input);
//handle bytes
}
DoSomething(true, BitConverter.GetBytes);
which may give you more flexibility.

Where the code is calling BitConverter.GetBytes, the type is TSource, so the call can't be statically bound by the compiler. You can work around this using dynamic invocation, meaning it'll compile fine and then get resolved at runtime:
…
public byte[] GetBytes(dynamic input)
{
return BitConverter.GetBytes(input);
}
You will pay a performance penalty for using dynamic invocation and if no suitable method to call is available you will get a runtime exception.

Given that there are "only" 10 overloads of BitConverter.GetBytes, it's not impossible to reflect them all explicitly like this:
public class Foo
{
public byte[] GetBytes(bool input) { return BitConverter.GetBytes(input); }
public byte[] GetBytes(char input) { return BitConverter.GetBytes(input); }
public byte[] GetBytes(double input) { return BitConverter.GetBytes(input); }
public byte[] GetBytes(float input) { return BitConverter.GetBytes(input); }
public byte[] GetBytes(int input) { return BitConverter.GetBytes(input); }
public byte[] GetBytes(short input) { return BitConverter.GetBytes(input); }
public byte[] GetBytes(long input) { return BitConverter.GetBytes(input); }
public byte[] GetBytes(uint input) { return BitConverter.GetBytes(input); }
public byte[] GetBytes(ulong input) { return BitConverter.GetBytes(input); }
public byte[] GetBytes(ushort input) { return BitConverter.GetBytes(input); }
}
It's not generic (which you had asked for), and isn't scalable to more complex examples, but if the numbers are small then it's an approach to consider.

If you are willing to take a performance hit, you can use reflection and an extension to object called GetBytes. example....
public static class Extensions
{
#region Fields
public static Type bcType;
#endregion
#region Constructor
static Extensions()
{
bcType = typeof(BitConverter);
}
#endregion
public static byte[] GetBytes(this object value)
{
Type typeObj = value.GetType();
MethodInfo miGetBytes = bcType.GetMethod("GetBytes", new Type[] { typeObj });
if (miGetBytes == null)
throw new InvalidOperationException("Method: GetBytes on BitConverter does not have an overload accepting one paramter of type: " + typeObj.FullName);
byte[] bytesRet = (byte[])miGetBytes.Invoke(null, new object[] { obj });
return bytesRet;
}
}
So GetBytes accepts an object. Then it get's it's type and tries to get the MethodInfo from BitConverter based on the type of object passed in. If it can't find an overload that accepts that type as a parameter it throws an InvalidOperation Exception. If it does, it calls it passing in the instance of obj as the value and returns the byte array.
E.g. Usage code,
//make sure the extensions namespace is defined where this code is run.
Console.WriteLine(((ushort)255).GetBytes().ToBase64());
Console.WriteLine(10.0.GetBytes().ToBase64());
Console.WriteLine(((int)2000000000).GetBytes().ToBase64());
Console.WriteLine(((short)128).GetBytes().ToBase64());
//Below causes an error
Console.WriteLine("cool".GetBytes().ToBase64()); //because BitConvert.GetBytes has no overload accepting an argument of type string.

You'll need to use reflection to do that.
Get the GetBytes method group from the BitConverter static type.
Pull out the overload for which the first parameter has type TSource.
Call that specific method via the Invoke method.
If you aren't familiar with some of this, I can expand the answer with code for those steps.
Edit: Or just use dynamic like others are suggesting and save yourself some work.

Your code doesn't compile because the compiler can't verify that any type for TSource will be accepted by BitConverter.GetBytes(). You can check for each type individually and cast:
public byte[] GetBytes <TSource> (TSource input)
{
var t = typeof(TSource);
return (t == typeof(int)) ? BitConverter.GetBytes((int) (object) input)
: (t == typeof(bool)) ? BitConverter.GetBytes((bool)(object) input)
: (t == typeof(char)) ? BitConverter.GetBytes((char)(object) input)
: null;
}

Related

wrap overloading function with generics

I want to wrap BitConverter with some extra functionalities. But I don't have to write out all the overloading functions like
BitConverter.GetBytes(int);
BitConverter.GetBytes(double);
...
Is there a way to write a single template function that wraps all the overloading functions? like
void GetBytes <T> (List<byte> byteList, T value)
{
....
byte[] result = BitConverter.GetBytes(value);
byteList.AddRange(result);
return;
}
You could write an extension method for IEnumerable<byte> I suppose:
class Program
{
static void Main(string[] args)
{
var target = new List<byte>();
BitConverter.GetBytes(10).AddBytesToTarget(target);
BitConverter.GetBytes(100d).AddBytesToTarget(target);
}
}
static public class Extensions
{
public static void AddBytesToTarget(this IEnumerable<byte> bytes, List<byte> target)
{
target.AddRange(bytes);
}
}
You cannot do it with generics since the overload resolution BitConverter.GetBytes will fail since T can be any type.
You could do it with dynamic:
void GetBytes(List<byte> byteList, dynamic value) {
....
byte[] result = BitConverter.GetBytes(value);
byteList.AddRange(result);
}
This will defer the overload resolution until runtime. Of course this also pushes type checking so if an invalid type was used for value you would get a runtime exception instead of a compiler error.
You can use dynamic type
Read this link of MSDN

C# Method overloading using dynamic params

I'm trying to write a tool for serialization of values. And I was hoping to get some nice syntax working.....
float f = 9999.0f;
ByteSerializer s = new ByteSerializer ();
s.Write(f);
Where the params of Write() could be anything and any number:
public void Write (params dynamic[] objects)
{
for (int i =0;i<objects.Length;i++) {
byteList.AddRange (GetBytes (objects[i]));
}
}
GetBytes() should now be called according to the type of the object that was passed:
public byte[] GetBytes ( object v)
{
//Shouldn't actually do anything since it's a dummy
return new byte[0];
}
public byte[] GetBytes ( System.Single v)
{
//Why is this not called?
return BitConverter.GetBytes (v);
}
But it will always go straight for the method that takes an object as parameter.
I initially tried (params object[]) as method parameters and found this behaviour to be rather obvious. But why does dynamic[] behave the same?
objects[i].GetType() reports a System.Single so what's going on here? Is what I am trying to do just not possible?
There is no reason this shouldn't work with dynamic exactly as you described. One of the primary features of the DLR is to do at runtime what would have been done at compile time if the types had been known then. For example, the following program:
public class Program
{
public static void Main(string[] args)
{
WriteItems("a string", (byte)1, 3f, new object());
}
private static void WriteItems(params dynamic[] items)
{
foreach(dynamic item in items)
{
Write(item);
}
}
private static void Write(byte b)
{
Console.WriteLine("Write byte: {0}", b);
}
private static void Write(float f)
{
Console.WriteLine("Write Single: {0}", f);
}
private static void Write(string s)
{
Console.WriteLine("Write string: {0}", s);
}
private static void Write(object o)
{
Console.WriteLine("Write object: {0}", o);
}
}
Produces the output:
Write string: a string
Write byte: 1
Write Single: 3
Write object: System.Object
Method overloading relies on knowing at compile time the types of all the arguments. Here, you can't know the argument types at compile time - because it's dynamic - so the compiler uses the lowest common type - which is object. The difference between object and dynamic is that dynamic allows late binding syntax - but that doesn't help you here.
If you want to call GetBytes for the correct types, you need to use reflection. Specifically, you want to use GetMethod to find an overload of GetBytes that matches the type of each argument, and then call it. with Invoke. Something like this(not tested):
byteList.AddRange (GetType()
.GetMethod("GetBytes", new Type[objects[i].GetType()])
.Invoke(null, new object[objects[i]]));
The dynamic type behaves like the object type. The only difference is that for dynamic the compiler does no type checking (so you can avoid compiler errors when working e.g. with COM).
What you intend, can be done anyway. But you must take the long road and do an explicit typechecking/cast in your for loop (a long but simple switch/case construct).
HTH Thomas

Is it possible to force an external class to call a specialized overload when the calling class is, itself, generic?

I am writing code that interfaces with an external API that I cannot change:
public class ExternalAPI
{
public static void Read(byte[] buffer);
public static void Read(int[] buffer);
public static void Read(float[] buffer);
public static void Read(double[] buffer);
}
It's important that I call the correct overloaded method when reading data into buffer, but once the data is read in, I will process it generically. My first pass at code that does that was:
public class Foo<T>
{
T[] buffer;
public void Stuff()
{
ExternalAPI.Foo(buffer);
}
}
C#, though, won't convert from T[] to byte[]. Is there a way to enumerate the types that T can represent explicitly? I've tried using a where T : clause, but there doesn't appear to be a way to say where T : {byte, int, float, double and nothing else ever}?
Following the advice here: Generic constraint to match numeric types, I added constraints to the generic, and also added a generic method to my simulated API that takes an object as its parameter
public class ExternalAPI
{
public static void Read(object buffer);
public static void Read(byte[] buffer);
public static void Read(int[] buffer);
public static void Read(double[] buffer);
}
public class Foo<T> where T: struct, IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable
{
T[] buffer;
public void Stuff()
{
ExternalAPI.Read(buffer);
}
}
This will compile and run happily, but the only method that is ever called is Foo(object buffer), even when T is byte. Is there a way to force methods of non-generic classes to use the most specific overload when the calling class is generic?
I've been in this situation before, and the only solution I've come up with is to test against the type of T and call the appropriate function;
public class Foo<T>
{
T[] buffer;
public void Stuff()
{
var type = typeof(T);
if (type == typeof(int[]))
{
...
}
else if (type == typeof(double[]))
{
...
}
}
}
Is there a way to force methods of non-generic classes to use the
most specific overload when the calling class is generic?
Normally, the overload resolution takes place at compile-time. Since the constraints on T, namely where T: struct, IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable, cannot point to any other overload than the one taking in object, that's the overload getting called.
If you are willing to use dynamic, the overload resolution will happen at run-time. Simply cast the argument to dynamic, like this:
public void Stuff()
{
ExternalAPI.Read((dynamic)buffer);
}
The bad thing about this is that it's slower because overload resolution has to set in when your program runs. But if T is one of byte, int, and so on, the corresponding overload with byte[], int[] etc. will be called. If T is something not supported, and if the object overload does not exist in ExternalAPI, this will fail at run-time, throwing an exception, but not until the Stuff method runs.
Another solution is to equip your Foo<T> class with a delegate to hold the correct method. It could be like:
T[] buffer;
readonly Action<T[]> readMethod;
public void Stuff()
{
readMethod(buffer);
}
//constructor
public Foo(Action<T[]> readMethod)
{
this.readMethod = readMethod;
}
But then people would have to instantiate your class like this:
new Foo<byte>(ExternalAPI.Read)
The right overload would be selected compile-time each place where people created instances of Foo<>. You could add checks in you instance constructor that readMethod is indeed a unicast delegate representing a method called Read defined by typeof(ExternalAPI).
A third solution is to make the readMethod field static, and include a static constructor that initializes readMethod. That would look ugly, but the static constructor would only run once for each type (byte, int, etc.) you used. The static constructor could throw an exception if people used a wrong T. Here's what the static constructor may look like:
static Foo()
{
if (typeof(T) == typeof(byte))
readMethod = (Action<T[]>)(Delegate)(Action<byte[]>)ExternalAPI.Read;
else if (typeof(T) == typeof(int))
readMethod = (Action<T[]>)(Delegate)(Action<int[]>)ExternalAPI.Read;
else if (typeof(T) == typeof(float))
readMethod = (Action<T[]>)(Delegate)(Action<float[]>)ExternalAPI.Read;
else if (typeof(T) == typeof(double))
readMethod = (Action<T[]>)(Delegate)(Action<double[]>)ExternalAPI.Read;
else
throw new Exception("The type parameter T can't be " + typeof(T));
}
Edit: Inspired by the first comment below, here's an attempt to make the static constructor use reflection instead:
static Foo()
{
var methInfo = typeof(ExternalAPI).GetMethod("Read", new[] { typeof(T[]), });
if (methInfo == null)
throw new Exception("ExternalAPI has no suitable method for " + typeof(T[]));
readMethod = (Action<T[]>)Delegate.CreateDelegate(typeof(Action<T[]>), methInfo);
}
I know it's a sad and redundant solution, but I think that it can't be done in a better way than this:
public void Stuff()
{
var bufferBytes = buffer as byte[];
if (bufferBytes != null)
{
ExternalAPI.Read(bufferBytes);
return;
}
var bufferInts = buffer as int[];
if (bufferInts != null)
{
ExternalAPI.Read(bufferInts);
return;
}
var bufferDoubles = buffer as double[];
if (bufferDoubles != null)
{
ExternalAPI.Read(bufferDoubles);
return;
}
ExternalAPI.Read(buffer);
}
To improve performance by casting as less as possible, reorder the checks and put the ones which are most frequently called on the top of the if/else chain. Even if the code could be made shorter by a if (buffer is byte[]) ExternalAPI.Read(buffer as byte[]); else... model, that would represent useless overhead (since you would basically be casting buffer twice).

How to write generic extension methods?

I am developing a generic wrapper around TryParse, as follows:
public delegate bool ParseDelegate<T>(string s, out T result);
public static T? ParseOrNull<T>(this string value, ParseDelegate<T> parse) where T : struct
{
T result;
var parsed = parse(value, out result);
return parsed ? result : (T?)null;
}
[Test]
public void ParsesValidInt()
{
Assert.AreEqual(1234, "1234".ParseOrNull<int>(int.TryParse));
}
[Test]
public void ParsesValidDecimal()
{
Assert.AreEqual(12.34M, "12.34".ParseOrNull<decimal>(decimal.TryParse));
}
This is kinda repetitive. Is there a way to avoid mentioning int.TryParse at all, so that my calls look as follows:
"1234".ParseOrNull<int>()
Is there a way to avoid mentioning int.TryParse at all, so that my calls look as follows:
Not directly, as TryParse isn't part of a shared interface. If there were a shared interface to these value types, this would be possible via a constraint.
Personally, I would not suggest using extension methods for this. I would rather write this as something more like:
public static class Parse
{
public delegate bool ParseDelegate<T>(string s, out T result);
public static T? FromString<T>(string value, ParseDelegate<T> parse) where T : struct
{
T result;
var parsed = parse(value, out result);
return parsed ? result : (T?)null;
}
public static int? ToNullableInt32(string value)
{
return FromString<int>(value, int.TryParse);
}
public static double? ToNullableDouble(string value)
{
return FromString<double>(value, double.TryParse);
}
}
This adds a bit of overhead up front, but allows you to write these very cleanly, ie:
int? first = Parse.FromString<int>("1234", int.TryParse);
int? second = Parse.ToNullableInt32("1234");
double? third = Parse.ToNullableDouble("1234");
I see little value in putting an extension method, especially on something like string (which is used everywhere), as it "pollutes" the compilation of string itself. You'll see this everywhere you use strings - basically, any time you use this namespace, you'll end up having these parse methods in your intellisense, etc. In addition, this seems more like a "utility" than something that should appear as built-in functionality of string itself, which is why I personally prefer a separate class for it.
In short no but you can add a new helper method:
public static int? ParseInt(this string value)
{
return value.ParseOrNull<int>(int.TryParse);
}
and then:
"1234".ParseInt();
Look at how Microsoft deals with several types . They provides one method for each type. Enumerable.Sum Method is a good example. If you want to simplify the calling code, you should provide the overloads for each types :
public static int? ParseOrNull<int>(this string value)
{
int result;
var parsed = int.TryParse(value, out result);
return parsed ? result : (T?)null;
}
public static long? ParseOrNull<long>(this string value)
{
long result;
var parsed = long.TryParse(value, out result);
return parsed ? result : (T?)null;
}
// same for ulong, long, uint, ushort, short, byte,
// bool, float, double, decimal. Do I forget one ?
I think it's more important to simplify calls than the method itself. In fact, there is not a huge number of types to deal with.
Yes, you can use Convert.ChangeType
public static T? ParseOrNull<T>(this string value) where T : struct, IConvertible
{
try
{
return (T)Convert.ChangeType(value, typeof(T));
}
catch (FormatException ex)
{
return null;
}
}
It wont have as good performance (use of try catch) as TryParse, but should work for all IConvertible types
The answer is a big YES. You're trying to exploit the existence of the static T.TryParse(string, out T) function on the types you're converting to, and we can do that pretty easily with a little reflection.
public static T? ParseOrNull<T>(this string str)
where T: struct, IConvertible
{
// find the TryParse method.
var parseMethod = typeof(T).GetMethod("TryParse",
// We want the public static one
BindingFlags.Public | BindingFlags.Static,
Type.DefaultBinder,
// where the arguments are (string, out T)
new[] { typeof(string), typeof(T).MakeByRefType() },
null);
if (parseMethod == null)
// You need to know this so you can parse manually
throw new InvalidOperationException(
string.Format("{0} doesn't have a TryParse(..) function!",
typeof(T).FullName));
// create the parameter list for the function call
var args = new object[] { str, default(T) };
// and then call the function.
if ( (bool)parseMethod.Invoke(null, args))
return (T?)args[1]; // if it returned true
// if it returned false
return null;
}
This is the original answer I provided, based on the idea that you need two different parse methods: One for value types and another for reference types.
public delegate bool ParseDelegate<T>(string s, out T result);
public static T? ParseOrNull<T>(this string str, ParseDelegate<T> Parse)
where T: struct
{
T result;
if (!Parse(str, out result))
return null;
return result;
}
public static T ParseOrNull<T>(this string str, ParseDelegate<T> Parse)
where T : class
{
T result;
if (!Parse(str, out result))
return null;
return result;
}
public static T? ParseOrNull<T>(this string value)
where T : struct
{
T result = default(T);
object[] parameters = new object[] { value, result };
foreach (System.Reflection.MethodInfo method in
typeof(T).GetMethods()
.Where(method => method.Name == "TryParse")
.Where(method => method.GetParameters().Length == 2) //as opposed to the 4 argument version
.Take(1) //shouldn't be needed, but just in case
)
{
method.Invoke(null, parameters);
}
return (T)parameters[1];
}
As Reed mentions, I'd rather not use an extension method of string. I'd just use Parser.Parse(string value). Easy fix though, just remove the 'this' and voila.

Generics in c# & accessing the static members of T

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()
}

Categories