Is it possible to constrain a generic method on specific types?
I want to write something like this:
public T GetValue<T>(string _attributeValue) where T : float, string
{
return default(T); // do some other stuff in reality
}
I'm mostly just trying to avoid having a giant switch statement inside the method or having to throw an exception if an invalid type is specified.
Edit: Ack. I knew string is not a value type. I started out with two numeric types earlier. Sorry.
You can't use generic constraints to express the limitations you are interested in. Generics are not meant to express variation based on disjoint types - they're meant to express variation that is unified over a hierarchy of types (or those implementing certain interfaces).
You have a few alternative choices, however. Which you choose depends on the exact nature of what you're trying to do.
Use differently named methods to express each operation. I tend to use this approach when each method is truly doing something different. You could argue that returning a different type of value from a method is essentially a different operation, and deserves its own unique name.
float GetFloat(string attrName) { }
string GetString(string attrName) { }
Provide a "default value" to allow the type to be inferred. In many designs where you ask for a value by name it useful to supply a default value. This can allow you to employ overloading to differentiate between which method to invoke (based on the type of the default value). Unfortunately, this approach is quite fragile - and breaks easily when passing literal values to overloads that accept numeric primitives (int vs. uint vs. long).
float GetValue(string attrName, float defaultValue) { ... }
string GetValue(string attrName, string defaultValue) { ... }
Use a generic method, but throw a runtime exception if the type isn't one of those you support. Personally I find this kind of ugly and in violation of the spirit of generics - generics should unify functionality over a hierarchy or a set of types implementing some interface. However, in some cases it makes sense to do so (if let's so one specific type cannot be supported, let's say). Another problem with this approach is that the signature of the generic method cannot be inferred from any parameters, so you would have to specify the type desired when calling it ... at which point it's not much better (from a syntax point of view) than having different method names.
T GetValue<T>( string attrName )
{
if( typeof(T) != typeof(string) ||
typeof(T) != typeof(float) )
throw new NotSupportedException();
return default(T);
}
// call it by specifying the type expected...
float f = GetValue<float>(attrName);
string s = GetValue<string>(attrName);
Use an out parameter instead of a return value. This approach works well, but it loses the concise syntax of being able to call a method and act on a return value, since you first have to declare a variable to populate.
void GetValue( string attrName, out float value )
void GetValue( string attrName, out string value )
// example of usage:
float f;
GetValue( attrName, out f );
string s;
GetValue( attrName, out s );
This is not possible to do with compile time support. You can do this check in the static constructor and throw an exception (in the case the T is defined on the type) or (in your case) in the method body itself, but in that case it would be a runtime validation.
No, you can not specify a range of types. If you want all primatives you can do (and i know string is not included)
where T: struct
No, it's not possible.
And string is a reference type, not a value type.
The closest you can get is constraining on all value types (minus Nullable types):
public T GetValue<T>(string _attributeValue) where T : struct
Depending on what you're actually doing inside the method, there may be various ways to achieve your goal (other than switch/case). Consider changing your example to be a little more meaningful...
One other option might also be to make your method private and provide public wrappers that are specific:
private T GetValue<T>(string _attributeValue) where T : struct
{
return default(T);
}
public float GetFloatValue(string _attributeValue)
{
return GetValue<float>(_attributeValue);
}
public int GetIntValue(string _attributeValue)
{
return GetValue<int>(_attributeValue);
}
That would allow you to constrain the public members of your class to the desired types but still use generic code internally so you don't have to repeat yourself.
Related
Let's say I have a generic List<ICalculation> which serves as a repository for all predefined calculations in my application...
I have a generic interface called ICalculation<T, U> which implements the more basic ICalculation.
public interface ICalculation
{
string Identifier { get; }
object Calculate(object inputData);
}
public interface ICalculation<in TIn, out TOut> : ICalculation
{
string Identifier { get; }
TOut Calculate(TIn inputData)
}
I also have an abstract class CalculationBase that implements this interface
public abstract class CalculationBase<TIn, TOut> : ICalculation<in TIn, out TOut>, ICalculation
{
public abstract string Identifier { get; }
public abstract Func<TIn, TOut> Calculation { get; }
public virtual TOut Calculate(TIn inputData)
{
return Calculate(inputData, Calculation);
}
virtual object ICalculation.Calculate(object inputData)
{
return (TOut)calculation((TIn)inputData);
}
public static TOut Calculate(TIn inputData, Func<TIn, TOut> calculation)
{
if (calculation == null || inputData == null)
return default(TOut);
return calculation(inputData);
}
}
So, now I have a whole bunch of calculations that implement CalculationBase that function over some input... one example:
public sealed class NumberOfBillableInvoices : CalculationBase<IClientAccount, int>
{
public override string identifier { get { return "#BillableInvoiceCount"; } }
public override Func<IClientAccount, int> Calculation
{
get { return inputData => inputData.Invoices.Count(i => i.IsBillable); }
}
}
Each calculation is targeted at a specific type of object and returns different outputs depending on the nature of the calculation. For instance: Currency calculations may return decimals, counters would probably return integers or longs etc.
I have a calculation repository that loads itself up on application load and when there comes a time that a formula must be evaluated, the calculation engine takes the object that is being queried against - in this example, if we have some concrete instance of type IClientAccount and we wish to evaluate some formula against it - for instance, levy $1.20 for each invoice after the first 5: "Math.Max(#BillableInvoiceCount - 5, 0) * $1.20". The engine goes and grabs all calculations where TIn is of type IClientAccount and matches the calculation with the token found in the formula (i.e. #BillableInvoiceCount). Then some calculation engine such as NCalc, FLEE or another calculation engine would evaluate the final equation.
So, my problem is that I don't wish to iterate through every calculation looking for the correct token - and realistically, tokens could collide if they spanned multiple object types. For instance I may want to use the same token to mean different things in different contexts. It would be easier if I could narrow the calculations in my repository to just those where TIn matches the object type I'm trying to calculate against.
I have a few trains of thought at this point -
1). Can I create a repository that marshals only the TIn part of my object? I think the answer to this is likely, no... but on the chance of it being possible, I don't have the first clue how to implement this - does anyone have any ideas?
2). Is there a way to query my repository for all calculations where TIn matches the type of the object I'm querying against? If so, how?
3). Do I have multiple repositories based on all the combinations of TIn/TOut that I have calculations for... and if so, how do I go about marrying up the correct repositories with the object I'm querying against? Because I'm still trying to match up a repository based on only the TIn portion...
4). Make all my calculations return doubles instead of allowing them to return different types, then my repositories can be typed to just the input type making them simpler... but while this is simple, semantically, it just feels wrong.
Thoughts?
Cheers in advance :)
Remember that generics are a compile time artifact, you need to know at the time of writing what class you want if you want to use them. If you need run-time checking then the non-generic way is probably best.
Assuming you know you have the correct types your object -> object overload should work fine for your purposes. The .NET framework will throw an exception if the mapping fails so you don't have to worry about a silent failure there.
1). Can I create a repository that marshals only the TIn part of my object? I think the answer to this is likely, no... but on the chance of it being possible, I don't have the first clue how to implement this - does anyone have any ideas?
Marshalling refers to conversion of the underlying data, you can likely simply pass around raw objects in this case since your ICalculation.Calculate method does a conversion for you. The only problem you might have is if TIn is a value type and you pass in a null (in which case your Calculate null handling would not occur)
2). Is there a way to query my repository for all calculations where TIn matches the type of the object I'm querying against? If so, how?
I would try using the non-generic version, unless you want cleaner exception trees it should do the job in this case.
3). Do I have multiple repositories based on all the combinations of TIn/TOut that I have calculations for... and if so, how do I go about marrying up the correct repositories with the object I'm querying against? Because I'm still trying to match up a repository based on only the TIn portion...
If you wanted to do this the trick would be to have your saving method only save TIn rather than both. For example a Dictionary<Type,ICalculation> where the Type is TIn.
4). Make all my calculations return doubles instead of allowing them to return different types, then my repositories can be typed to just the input type making them simpler... but while this is simple, semantically, it just feels wrong.
One thing to be careful of here, my suggestions only work if you aren't doing any conversions between method calls. If you have an int in an object and you try to convert it to a double it will fail.
You could avoid this by calling Convert.ChangeType instead of doing a direct cast. It would work like so:
object ICalculation.Calculate(object inputData)
{
if (inputData == null && typeof(TIn).IsValueType)
return default(TOut);
return Calculate((TIn)Convert.ChangeType(inputData, typeof(TIn));
}
Note a couple of changes to the method:
I added an explicit null handler for value types, since Convert.ChangeType would just throw an exception.
I call the generic form of Calculate in case it was overloaded.
I made it non-virtual, unless you really have a good reason, you really shouldn't be overloading this method, since it just provides the symmetry of the two interfaces.
I don't convert the result. Both calculation and Calculate are guaranteed to return TOut so a conversion is redundant.
The addition of ChangeType which would allow you to silently handle passing an int into a decimal.
Note that there is a danger with ChangeType, it will be similar to an explicit cast. It will do its best to do the conversion no matter what happens to your data. It seems like overflows will be handled as expected, but truncations will happen silently.
The main point there is test your edge cases if you have any like that.
If you know everything derives from CalculationBase<,>, I suppose you could do:
// can also be made an extension method
static bool HasCorrectInType(ICalculation calc, Type desiredInType)
{
var t = calc.GetType();
do
{
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(CalculationBase<,>))
return t.GetGenericArguments()[0].IsAssignableFrom(desiredInType);
t = t.BaseType;
} while (t != null)
throw new Exception("The type " + calc.GetType() + " not supported");
}
Then use it like this:
List<ICalculation> repository = XXX;
var matches = repository.Where(c => HasCorrectInType(c, type));
Edit: New idea: If you put a new property:
public Type InType
{
get { return typeof(TIn); }
}
into your abstract class CalculationBase<TIn, TOut>, and also add this property to your non-generic interface ICalculation, then you won't have to iterate through the base classes, but can say calc.InType.IsAssignableFrom(desiredInType) directly.
I think the simplest solution should be picked. You can use reflection to get the specific type or just return double in all cases. If it is an intensive data processing, trying to find the specific type might slow it down, so returning a double or integer is totally fine.
Ok,
I've got a bit of code that I don't like very much. Given that I didn't write it and merely inherited it, it occurs to me that I could clean it up a little. Basically, we have an object for settings that is persisted with NHibernate. I won't bore you with the implementation details except to say that it contains a dictionary that has the actual values we're keeping in the database.
Our typical property implementation looks like this:
public string MyDumbProperty
{
get { return GetStringValue("MyDumbProperty", string.Empty); }
set { SetValue("MyDumbProperty", value);}
}
Now, it's probably obvious from the implementation above that we have separate Getxxxx methods for each of the types we return (strings, ints, longs, floats, etc.), with the second parameter being a default value. What I want is to be able to do something like the following:
public string MyDumbProperty
{
get { return GetValue("MyDumbProperty", string.Empty); }
set { SetValue("MyDumbProperty", value);}
}
I have a couple of reasons for wanting to do this. The big one is that I have a personal dislike of methods named based on what types of parameters they take. The second is that I'd like to make a resharper template for this crap. Then I could just fill in the name of the property and the type and be done (presuming that resharper could give a reasonable default value for the type).
I had thought of making a generic method GetValue that returned a T, but I'm not sure how I need to set up the generic constraints so this is doable. The types being returned from this will all be basic types (strings, ints, etc). There are a couple that return arrays, but I could always do something different on those. This isn't a high priority issue, by any means, but it annoys me every time I see it. I just think there should be a better way to do this.
I suppose a first step would be to just rename the various methods. Since they vary on what type is being passed for the default in the second parameter, I could at least coerce them to the same name. But I could I do better than that? It would be great if I could get rid of the multiple bits of repetitive code in each method that are only different in terms of the datatype being used (TryParse in all the numeric ones).
I think you might be able to get away with a generic method if the guts of it aren't too complicated. For example, maybe something like this:
public T GetValue<T>(string name, T ifNull) where T : IConvertible
{
string value = GetProperty(name);
if (value == null)
return ifNull;
try
{
return (T)Convert.ChangeType(value, typeof(T));
}
catch
{
return ifNull;
}
}
For arrays, you might need a GetArrayValue function that does something different.
You can use default(T) to get the default value of a type.
public T Get<T>(string propertyName)
{
object obj;
if (propertyBag.TryGetValue(propertyName, out obj)) {
return (T)obj;
}
if(typeof(T) == typeof(string)) {
return String.Empty;
}
return default(T);
}
UPDATE
As an alternative you could have two overloads, one accepting an explicit default value.
public T Get<T>(string propertyName)
{
return Get<T>(propertyName, default(T));
}
public T Get<T>(string propertyName, T defaultValue)
{
object obj;
if (propertyBag.TryGetValue(propertyName, out obj)) {
return (T)obj;
}
return defaultValue;
}
The great thing about .net generics is that they can be implicitly used when it is clear which parameters they represent. Not sure about the grammar on that sentence, but a lot surer of that it's possible based on using it a lot..
e.g. for the GetValue:
public T GetValue<T>(string PropertyName, T DefaultValue)
{
}
.... return GetValue("Prop1", 4); //T = int
.....return GetValue("Prop2", string.Empty) //T= string
//for nullable times, you can always include the generic parameter
GetValue<int[]>("Prop3",null);
//or by 'strongly typing' the null value:
GetValue("Prop3", (int[])null); //for set this isn't a problem, since 'value' already is strongly typed
the same for setting
public void SetValue<T>(string PropertyName, T Value)
{
}
WARNING: THIS CODE SUCKS, SEE ANTHONY'S COMMENTS
Which is faster?
1.
public bool IsValueType<T>(T obj){
return obj is ValueType;
}
2.
public bool IsValueType<T>(T obj){
return obj == null ? false : obj.GetType().IsValueType;
}
3.
public bool IsValueType<T>(T obj){
return default(T) != null;
}
4.Something else
You aren't really testing an object - you want to test the type. To call those, the caller must know the type, but... meh. Given a signature <T>(T obj) the only sane answer is:
public bool IsValueType<T>() {
return typeof(T).IsValueType;
}
or if we want to use an example object for type inference purposes:
public bool IsValueType<T>(T obj) {
return typeof(T).IsValueType;
}
this doesn't need boxing (GetType() is boxing), and doesn't have problems with Nullable<T>. A more interesting case is when you are passing object...
public bool IsValueType(object obj);
here, we already have massive problems with null, since that could be an empty Nullable<T> (a struct) or a class. But A reasonable attempt would be:
public bool IsValueType(object obj) {
return obj != null && obj.GetType().IsValueType;
}
but note that it is incorrect (and unfixable) for empty Nullable<T>s. Here it becomes pointless to worry about boxing as we are already boxed.
My first answer would be to write a simple test and find out for yourself.
My second answer (without any testing on my part, of course) would be option 1. It is the simplest check. The second method involves two separate checks while the third involves creating a default instance of a type.
You should also consider readability. The framework already gives you the ability to have the following in your code:
if(someObj is ValueType)
{
// Do some work
}
Why even bother creating a method that would simply turn the above statement into (assuming you made your method static and allowed the compiler to infer the generic type):
if(IsValueType(someObj))
{
// Do some work
}
Defining a struct actually defines two types: a value type, and a class type which derives from System.ValueType. If a request is made to create a variable, parameter, field, or array (collectively, 'storage location') of a type which derives from System.ValueType, the system will instead create a storage location which will store the object's fields rather than storing a reference to an object in which those fields appear. On the other hand, if a request is made to create an instance of a type deriving from System.ValueType, the system will create an object instance of a class which derives from System.ValueType.
This may be demonstrated by creating a struct which implements IValue:
interface IValue {int value {get; set;}};
struct ValueStruct : IValue
{
public int value {get; set;}};
}
with generic test routine and code to wrap it:
static void Test<T>(T it) where T:IValue
{
T duplicate = it;
it.value += 1;
duplicate.value += 10;
Console.WriteLine(it.value.ToString());
}
static void Test()
{
ValueStruct v1 = new ValueStruct();
v1.value = 9;
IValue v2 = v1;
Test<ValueStruct>(v1);
Test<ValueStruct>(v1);
Test<IValue>(v1);
Test<IValue>(v1);
Test<IValue>(v2);
Test<IValue>(v2);
}
Note that in every case, calling GetType on the parameter passed to Test would yield ValueStruct, which will report itself as a value type. Nonetheless, the passed-in item will only be a "real" value type on the first two calls. On the third and fourth calls, it will really be a class type, as demonstrated by the fact that a change to duplicate will affect it. And on the fifth and sixth calls, the change will be propagated back to v2, so the second call will "see" it.
static class Metadata<T>
{
static public readonly Type Type = typeof(T);
static public readonly bool IsValueType = Metadata<T>.Type.IsValueType;
}
//fast test if T is ValueType
if(Metadata<T>.IsValueType) //only read static readonly field!
{
//...
}
There are two rules:
1-All Classes are reference types such as Object and String, so it's supported by .NET Framework classes.
2-All structures are value types such as bool and char, even though it contain reference member, so it's supported by .NET Framework structures.
Simply right click on any type and Go To Definition if it's a Class so that means it a reference type else if it's a Struct so that means it's a value type :)
You can use
obj.GetType().IsValueType
This uses reflection but clear way instead of care of boxing unboxing.
I'm currently rewriting parts of a custom RPC mechanism (which cannot be replaced by something else, so don't suggest that ;-) ). The arguments of a call are collected in a custom collection that uses a dictionary internally. There is a method T Get<T>(string) to retrieve a named argument. For optional arguments, I wanted to add a TryGet<T>(string) method that returns the argument or null if it doesn't exist, so that the calling code can provide a default value using the null coalescing operator. Of course, for a value type this doesn't work, but I could use T? instead, which is what I want.
So what I have is this:
public class Arguments
{
// lots of other code here
public T TryGet<T>(string argumentName) where T : class
{
// look up and return value or null if not found
}
public T? TryGet<T>(string argumentName) where T : struct
{
// look up and return value or null if not found
}
}
With that, I'd like to be able to do the following:
return new SomeObject(
args.TryGet<string>("Name") ?? "NoName",
args.TryGet<int>("Index") ?? 1
);
Since the constraints are mutually exclusive, the compiler should be able to produce the correct code (it's always possible to infer the call from the generic type given at the call site). The compiler complains that the type already defines a member called "TryGet" with the same parameter types.
Is there any way to make something like this work without giving the two methods different names?
Constraints are not part of the signature. thus the answer to your question is no.
The way classes in the .NET Framework handle this scenario is TryGetValue with an out parameter. The return value is an indicator of whether the get was successful, where the out parameter contains the value requested (on success) or a suitable default value (on failure).
This pattern makes the implementation very simple for reference and value types. You would only need a single method to handle both scenarios.
For an example of this pattern, see Dictionary<TKey,TValue>.TryGetValue.
The reason this doesn't work is because you cannot have two methods with the same name and same argument types (the return type is not taken into account for method overloading). Instead you could define a single method without the generic constraint which will work for both value and reference types:
public T TryGet<T>(string argumentName)
{
if (!_internalDictionary.ContainsKey(argumentName))
{
return default(T);
}
return (T)_internalDictionary[argumentName];
}
An alternative solution could be this one:
public class Arguments {
public T Get<T>(string argumentName,T defaultValue) {
// look up and return value or defaultValue if not found
}
}
return new SomeObject(
args.Get<string>("Name","NoName"),
args.Get<int>("Index",1)
);
In that particular case you would not even have to specify the generic type, as it could be inferred by the default parameter:
return new SomeObject(
args.Get("Name","NoName"),
args.Get("Index",1)
);
Although it does not work directly due to identical argument types, You can do that by adding optional defaultValue parameter which defaults to null:
public class Arguments
{
// lots of other code here
public T? TryGet<T>(string argumentName, T? defaultValue = null) where T : class
{
// look up and return value or null if not found
}
public T? TryGet<T>(string argumentName, T? defaultValue = null) where T : struct
{
// look up and return value or null if not found
}
}
The reason this one works is that second argument type is different for both contraints (In the the method with class constraint it is simply T, and in the method with struct constraint it is Nullbale<T>).
Following code works as you would expect:
var args = new Arguments();
var stringValue = args.TryGet<string>("Name") ?? "NoName";
var intValue = args.TryGet<int>("Index") ?? 1;
(Thanks everyone for the answers, here is my refactored example, in turn another StackOverflow question about the Single Responsibility Principle.)
Coming from PHP to C#, this syntax was intimidating:
container.RegisterType<Customer>("customer1");
until I realized it expresses the same thing as:
container.RegisterType(typeof(Customer), "customer1");
as I demonstrate in the code below.
So is there some reason why generics is used here (e.g. throughout Unity and most C# IoC containers) other than it just being a cleaner syntax, i.e. you don't need the typeof() when sending the type?
using System;
namespace TestGenericParameter
{
class Program
{
static void Main(string[] args)
{
Container container = new Container();
container.RegisterType<Customer>("test");
container.RegisterType(typeof(Customer), "test");
Console.ReadLine();
}
}
public class Container
{
public void RegisterType<T>(string dummy)
{
Console.WriteLine("Type={0}, dummy={1}, name of class={2}", typeof(T), dummy, typeof(T).Name);
}
public void RegisterType(Type T, string dummy)
{
Console.WriteLine("Type={0}, dummy={1}, name of class={2}", T, dummy, T.Name);
}
}
public class Customer {}
}
//OUTPUT:
//Type=TestGenericParameter.Customer, dummy=test, name of class=Customer
//Type=TestGenericParameter.Customer, dummy=test, name of class=Customer
One reason when generics are very useful is when the generic type parameter is used as the type of a parameter or as the return type of the method.
That means, you can write methods like
public T GetAs<T>(string name)
where the return type can be checked by the compiler and boxing value types can sometimes be avoided.
The caller would write:
int value = GetAs<int>("foo");
Whithout generics, you would have to write
public object GetAs(Type t, string name)
and the caller has to cast the result again:
int value = (int)GetAs(typeof(int), "foo");
A primary reason is the type safety at compile time. If you are passing two Type objects you are placing the responsibility at the developer instead of the compiler.
This is also why many IoC containers utilizes it, as your compiler will complain if an concrete type isn't inheriting the abstract type.
public void Register<TAbstract, TConcrete>() where TConcrete : TAbstract
{
}
This code will only work if TConcrete is implementing or inheriting TAbstract. If this method took two Type parameters, your method should validate this relationship.
A simple answer is type inference where possible.
If the generic type is used in the method signature, you can omit it because the type could be inferred:
void SomeMethod<T>(T x, T y) where T : IComparable<T> {
Console.WriteLine("Result: {0} to {1} is {2}", x, y, x.CompareTo(y));
}
So the usage is simplified:
SomeMethod(3, 4); // instead of SomeMethod<int>(3, 4);
SomeMethod("one", "two"); // instead of SomeMethod<string>("one", "two");
If the generic type parameter is not used in the method signature the type inference is not possible:
var emptySequence = Enumerable.Empty<int>();
I think one of the primary uses is type safety with arguments and return values. In your example case, there is not much use for generics, because the input/output types (string) do not match the generic case (customers).
A more appropriate use might be:
public T RegisterType<T>(string name)
{
T obj = new T();
obj.DoSomething();
return obj;
}
or maybe
public void DoSomething<T>(T obj)
{
//operate on obj
}
If you didn't use Generics, you'd either have to overload a method for each type you want to support, or you'd have to accept the parameter as an object and perform casting logic.
For one example, compare the code needed to create an instance of your type using the typeof option versus a generic. Or return an instance of the type. Or accept an instance of the type as an argument. Or set a property on an instance of the type.
In general, if you will be working only with the type itself you can accept a type parameter. If you want to do anything with an instance of the type, use a generic.
Another reason to use a generic is if you want to apply constraints to the type. For example, you can require the type to implement one or several interfaces, inherit another type, be a reference type or value type, have a default constructor, or some combination of the above. The compiler will enforce this so you can't build code that doesn't comply with your requirements.
I'd say the best reason is type safety, using the "where" keyword, to ensure that the generic type is of a certain type (or sub-class/implementor). Using "typeof" will let you send anything through.