I need to create an extension method to array class, but this extension method must be able to accept many data types, so it also must be generic.
In the code bellow the extension method just accept byte data type. I want it to also accept ushort and uint for instance.
I believe that the best way to do that is creating a generic type here. But how can I do that using arrays?
Thanks!!!
public static class MyExtensions
{
public static int GetLastIndex(this byte[] buffer)
{
return buffer.GetUpperBound(0);
}
}
Generics in extension methods aren't really anything special, they behave just like in normal methods.
public static int GetLastIndex<T>(this T[] buffer)
{
return buffer.GetUpperBound(0);
}
As per your comment, you could do something like the following to effectively restrict the type of T (adding guard statements).
public static int GetLastIndex<T>(this T[] buffer) where T : struct
{
if (!(buffer is byte[] || buffer is ushort[] || buffer is uint[]))
throw new InvalidOperationException(
"This method does not accept the given array type.");
return buffer.GetUpperBound(0);
}
Note: As Martin Harris pointed out in a comment, you don't actually need to use generics here. The Array type from which all arrays derive will suffice.
If you want a more elegant solution, at the cost of slightly more code, you could just create overloads of the method:
public static int GetLastIndex(this byte[] buffer)
{
return GetLastIndex(buffer);
}
public static int GetLastIndex(this ushort[] buffer)
{
return GetLastIndex(buffer);
}
public static int GetLastIndex(this uint[] buffer)
{
return GetLastIndex(buffer);
}
private static int GetLastIndex(Array buffer)
{
return buffer.GetUpperBound(0);
}
public static class MyExtensions
{
public static int GetLastIndex<T>(this T[] buffer)
{
return buffer.GetUpperBound(0);
}
}
Same way you do generics in normal (non-extension) methods: Use a placeholder type name introduced in the generic syntax:
public static int GetLastIndex<TElement>(this TElement[] buffer)
#RHaguiuda
You can make constraint like
public static class MyExtensions{
public static int GetLastIndex<T>(this T[] buffer) where T: Integer
{
return buffer.GetUpperBound(0);
}}
But, type used as a constraint must be an interface, a non-sealed class or a type parameter
Related
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
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;
}
I have a rather simple problem, but there seems to be no solution within C#.
I have around 100 Foo classes where each implement a static FromBytes() method. There are also some generic classes which shall use these methods for its own FromBytes(). BUT the generic classes cannot use the static FromBytes() methods, because T.FromBytes(...) is illegal.
Do I miss something or is there no way to implement this functionality?
public class Foo1
{
public static Foo1 FromBytes(byte[] bytes, ref int index)
{
// build Foo1 instance
return new Foo1()
{
Property1 = bytes[index++],
Property2 = bytes[index++],
// [...]
Property10 = bytes[index++]
};
}
public int Property1 { get; set; }
public int Property2 { get; set; }
// [...]
public int Property10 { get; set; }
}
//public class Foo2 { ... }
// [...]
//public class Foo100 { ... }
// Generic class which needs the static method of T to work
public class ListOfFoo<T> : System.Collections.Generic.List<T>
{
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
var count = bytes[index++];
var listOfFoo = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
listOfFoo.Add(T.FromBytes(bytes, ref index)); // T.FromBytes(...) is illegal
}
return listOfFoo;
}
}
I think it would be unfair to choose an answer as accepted answer, after all answers and comments have contributed in different ways with their different views. It would be nice if someone writes a good overview about the different approaches with their pros and cons. That should be accepted after it helps future developers best.
The best option would be to simply accept the specific FromBytes function as a delegate to your generic FromBytes function. This avoids both the performance cost and lack of compile time verifiability that comes along with using reflection.
public delegate T FromBytesFunc<T>(byte[] bytes, ref int index);
public static List<T> FromBytes<T>(byte[] bytes, ref int index,
FromBytesFunc<T> function)
{
var count = bytes[index++];
var listOfFoo = new List<T>();
for (var i = 0; i < count; i++)
{
listOfFoo.Add(function(bytes, ref index));
}
return listOfFoo;
}
Note that if you make the method, rather than the class it's in, generic, you can get the compiler to infer the generic argument. It could be called like so:
var list = SomeClass.FromBytes(bytes, ref index, Foo1.FromBytes);
The problem is that you're trying to use FromBytes as an extension method when it's not. From what I gather, you're trying to call the appropriate FromBytes for whatever <T> is, as defined in whatever class you've already created for T.
What you need to do is call the method via reflection.
Try looking at some of these threads for help on how to accomplish this.
Use Reflection to call generic method on object instance with signature: SomeObject.SomeGenericInstanceMethod<T>(T argument)
How do I use reflection to call a generic method?
Calling generic method using reflection in .NET
How to call generic method with a given Type object?
Could you just implement the static FromBytes method generically in a utility class? Then do something like this?
listOf.Add(Utility.FromBytes<T>(bytes, ref index));
That utility method might be a bit ugly if each methods FromBytes is a lot different, but it wouldn't be too bad, it's all code that used to live in each class anyway.
Something like this:
public static class Utility
{
public static T FromBytes<T>(byte[] bytes, ref int index)
{
if (typeof(T) is Foo1)
{
return Foo1.GetBytes(bytes, ref index);
}
//etc....
}
}
You could also hide that reflection code here as pointed out by other answers. Unfortunately there doesn't seem to be a very clean way to do this, but hiding the messy stuff in a utility method may be the best option.
You can use reflection to find the method on that type and then build a delegate for it. Something like:
delegate T FromBytesFunc<T>(byte[] bytes, ref int index);
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
FromBytesFunc<T> fromBytes =
(FromBytesFunc<T>)Delegate.CreateDelegate(
typeof(FromBytesFunc<T>), typeof(T).GetMethod("FromBytes")
var count = bytes[index++];
var listOf = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
listOf.Add(fromBytes(bytes, ref index));
}
return listOf;
}
You can try something like this:
sealed class RetType
{
public object Value
{
get;
private set;
}
public int Index
{
get;
private set;
}
public RetType(object value, int index)
{
Value = value;
Index = index;
}
}
public class ListOfFoo<T> : System.Collections.Generic.List<T>
{
static readonly Dictionary<Type, Func<byte[], int, RetType>> dic = new Dictionary<Type, Func<byte[], int, RetType>>
{
{
typeof(Foo1),
new Func<byte[], int, RetType>((bytes, index) =>
{
var value = Foo1.FromBytes(bytes, ref index);
return new RetType(value, index);
})
}
// add here others Foo
};
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
var count = bytes[index++];
var listOf = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
var o = dic[typeof(T)](bytes, index);
listOf.Add((T)o.Value);
index = o.Index;
}
return listOf;
}
}
You build a lookup to finde the method you want to call to build the instance.
Not sure if this works for you, but it is an option:
Define an interface IHaveFromBytesMethod<T> which defines a FromBytes(...) instance method.
Make all Foo# types implement this interface. (If you do not want this instance method to be visible immediately, you could implement the interface explicitly.)
All implementations of the instance method simply forward the call to the static method of that type.
Restrict type parameter T in your ListOfFoo<T> class to implement this interface and to provide a parameterless constructor.
When you need the static method, construct a new dummy object of type T using the parameterless constructor and then call the instance method on that dummy instance.
Interface:
public interface IHaveFromBytesMethod<T>
{
T FromBytes(byte[] bytes, ref int index);
}
One of the Foo# classes:
public class Foo1 : IHaveFromBytesMethod<Foo1>
{
public Foo1()
{
// ...
}
public static Foo1 FromBytes(byte[] bytes, ref int index)
{
// ...
}
public Foo1 FromBytes(byte[] bytes, ref int index)
{
// within the instance method simply call the static method
return Foo1.FromBytes(bytes, ref index);
}
}
The modified ListOfFoo<T> class:
// requires T to implement the interface and provide a parameterless ctor!
public class ListOfFoo<T> : System.Collections.Generic.List<T>
where T : IHaveFromBytesMethod<T>, new()
{
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
// create dummy instance for accessing static method via instance method
T dummy = new T();
var count = bytes[index++];
var listOfFoo = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
// instead of calling the static method,
// call the instance method on the dummy instance
listOfFoo.Add(dummy.FromBytes(bytes, ref index));
}
return listOfFoo;
}
}
I'd like to thank you all guys, you gave me some insights to think about. I've considered each approach and thought about its pros and con and wrote the following code. What do you think about? I think it is a good compromise for usability, readability and performance. It only lacks the compiler check.
public class ListOfFoo<T> : System.Collections.Generic.List<T>
{
private static readonly FromBytesFunc<T> BytesFromFunc =
(FromBytesFunc<T>)System.Delegate.CreateDelegate(
typeof(FromBytesFunc<T>),
typeof(T).GetMethod("FromBytes"));
private delegate T2 FromBytesFunc<out T2>(byte[] bytes, ref int index);
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
var count = bytes[index++];
var listOfFoo = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
listOfFoo.Add(BytesFromFunc(bytes, ref index));
}
return listOfFoo;
}
}
This shall be the summary for all future viewers.
Since you cannot just call the method, the main problem is to get the delegate. There are two approaches:
via reflection
from the caller
You might think reflection is slow, but performance is not an issue. If the delegate is stored in a static field, it only needs to be done once per class, because generic types don't share static members.
Compile time verifiability is an issue. If you care much about compile time verifiability you should go with passing the delegate from the caller. If you care more about a clean method call you have to sacrifice the compile time verifiability.
PS: Some people have suggested to have a dictionary or a switch/case or if/else where the delegates are stored. This is something you shouldn't do. This has no advantage over storing the delegate in a static field of the generic class (generic types don't share static members).
I'm wondering something. Instead of writing String.Format("{0:X}", num); to convert numbers to hex. Is there a way where i could extend string directly so that i could simply write num.ToHex(); instead?
You can create extension method:
public static class IntExtensions
{
public static string ToHex(this int source)
{
return string.Format("{0:X}", source);
}
}
Execute like this:
string hexNum = 1234.ToHex();
It's called extension method. However, it should be set on numeric type, to allow {0:X} string format:
public static class Extensions
{
public static string ToHex(this int source)
{
return string.Format("{0:X}", source);
}
}
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).