C# functions on generic numeric primitives [duplicate] - c#

Suppose we have an interface with a single generic method:
public interface IExtender
{
T GetValue<T>(string tag);
}
and a simple implementation A of it that returns instances of two different types (B and C) depending on the "tag" parameter:
public class A : IExtender
{
public T GetValue<T>(string tag)
{
if (typeof(T) == typeof(B) && tag == null)
return (T)(object) new B();
if (typeof(T) == typeof(C) && tag == "foo")
return (T)(object) new C();
return default(T);
}
}
is it possible to avoid the double cast (T)(object)? Or, is there a way to tell the compiler "hey, I am sure that this cast won't fail at runtime, just let me do it without first casting to object!"

Or, is there a way to tell the compiler "hey, I am sure that this cast won't fail at runtime, just let me do it without first casting to object!"
No, the language is deliberately designed to prevent this. Eric Lippert blogged about this recently. I agree it's annoying, but it does make a certain kind of sense.
To be honest, "generic" methods like this are usually a bit of a design smell. If a method has to have special cases for various different types, you should at least consider using separate methods instead. (GetB, GetC)

public T MyMethod<T>(string tag) where T : class
{
return new A() as T;
}

check this sample:
public T GetValue<T>(string tag) where T : class, new()
{
if (typeof(T) == typeof(B) && tag == null)
return new T();
if (typeof(T) == typeof(C) && tag == "foo")
return new T();
return default(T);
}
no cast needed, you can create instance of "T", just add the generic constraint that saying that T is a class and it have parameterless constructor so you don't need to create another base types and you can be sure that only suitable types will go through this generic method.

You can use dynamic to store your real result, but you have to be sure the generic argument type is the right type you return.
TResult GetResult<TResult>()
{
dynamic r = 10;
return r;
}

No, that is not possible. The only way to do so would be to let the compiler know about additional assumptions on T. As evidenced by the list of generic parameter constraints, there is no constraint defined in C# to require availability of a specific cast.

if you let B and C implement the same interface you could use a type constraint on your T. Probably not exactly what you want, but as suggested also by others what you want is not really possible.
public interface IclassBndC {}
public class B : IclassBandC {}
public class C : IclassBandC {}
public class A : IExtender
{
public T GetValue<T>(string tag) where T : IclassBandC
{
if (tag == null)
return new B();
if (tag == "foo")
return new C();
return default(T);
}
}

Related

Force C# Cast To Generic

There is a tool I'm modifying as I want to be able to use a generic type.
It has properties "AsDouble", "AsBool", etc.
I want to force a typecast and I don't care if it throws in runtime. I just want it to compile.
So... this does not compile...
public T As<T>()
{
Type type = typeof(T);
if (type == typeof(Double))
{
return (T)(AsDouble);
}
// more conditionals
}
Yet this does...
public T As<T>()
{
Type type = typeof(T);
if (type == typeof(Double))
{
return (T)(AsDouble as object);
}
// more conditionals
}
Why is it acting like this? How do I make it stop complaining and just do what I ask it too? Or is there a much better way of doing this than what I have in mind?
// Not duplicate of the one suggested. (Type1)Type2 does not work... I am wondering why converting from T1 to T2 to T3 works but not T1 to T3. (T1 being double, T2 being object, T3 being generic type.) Please read my question before flagging it as a duplicate.
If T does not have any type constraints the compiler will not know what type of casting to do as the relation between T and double is not known. The only way I know to achieve what you want is to cast through object, which might generate a box/unbox operation (it might get optimized but I am not sure).
In the case of generic methods with clear specializations by type I have employed the following pattern:
class Owner
{
class AsHelper<T>
{
public static Func<Owner, T> As;
}
static Owner()
{
AsHelper<double>.As = _ => _.AsDouble;
// Other implementations
}
public T As<T>() where T: struct
{
if(AsHelper<T>.As != null)
{
return AsHelper<T>.As(this);
}
else
{
// Default implementation or exception
return default(T);
}
}
}
This keeps the specializations in their own methods. From my performance testing it does about the same as the if base approach. Since statics are per generic class instantiation in .NET not per generic class definition the As field of AsHelper<T> will have a different value for each T

Derived Types and Generics

I have a type that uses generics. Let's call it FlowerDescriptor<T> some flowers are described using numbers, others using strings etc.
so FlowerDescriptor<int>; FlowerDescriptor<string>; etc
I want a mechanism (probably extension methods) for doing 2 things
seeing if something is a FlowerDescriptor and
seeing what the descriptor is.
I.e.
FlowerDescriptor<string>.GetType().IsFlowerDescriptor == true
string.GetType().IsFlowerDescriptor == false.
equally I might derive from FlowerDescriptor<int> i.e. class NumberedFlower: FlowerDescriptor<int>
new NumberedFlower.GetType().IsFlowerDesriptor == true;
as above but returns the type
FlowerDescriptor<string>.GetType().GetFlowerDescriptor() == typeof(string)
FlowerDescriptor<int>.GetType().GetFlowerDescriptor() == typeof(int)
new NumberedFlower.GetType().GetFlowerDescriptor() == typeof(int)
I have played about with variations of IsAssignableFrom and it feels like that ought to work with typeof(FlowerDescriptor<>).IsAssignableFrom(typeof(FlowerDescriptor<string>))
but it doesn't work. If it add the generic type however it does.
I am currently exploring GetInterfaces to know available interfaces. It'd be great to actually understand what I am doing wrong too..
Unless you want to add interfaces into the mix, the only choice you have is to
Detect that the type is actually a FlowerDescriptor<T>
or detect that the type inherits from something that is a FlowerDescriptor<T>
Unfortunately I don't think you can use IsAssignableFrom when it comes to open generics which means we're left with walking the inheritance chain up to the base classes.
Here is an example piece of code that would do the right thing:
public static bool IsFlowerDescriptor(this Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(FlowerDescriptor<>))
return true;
if (type.BaseType != null)
return type.BaseType.IsFlowerDescriptor();
return false;
}
Here's a .NET Fiddle you can experiment with.
I would not expect the string or int class to know if its a descriptor, it makes a lot more sense to get that information from the FlowerDescriptor.
That being said if you want to use reflection you could get the generic type definition from the FlowerDescriptor instance
FlowerDescriptor<int> f = new FlowerDescriptor<int>();
Type t = f.GetType();
Type[] typeArguments = t.GetGenericArguments();
//check if type you care about is in typeArguments
Here is how you would get those two values:
bool isFlowerDescriptor = x is FlowerDescriptor<object>;
Type descriptorType = x.GetType().GetGenericArguments()[0];
You could wrap these in extension methods if you like. And add null-checks etc.
You might consider having a non-generic base class. Then your structure could look like:
public abstract class FlowerDescriptor { }
public class FlowerDescriptor<T> : FlowerDescriptor { }
public class NumberedFlower : FlowerDescriptor<int> { }
Your 2 extensions would be:
public static class Extensions
{
public static bool IsFlowerDescriptor(this object o)
{
return o is FlowerDescriptor;
}
public static Type GetFlowerDescriptor<T>(this FlowerDescriptor<T> o)
{
return typeof (T);
}
}
and you'd use it like:
public static void Main()
{
Console.WriteLine(new NumberedFlower().IsFlowerDescriptor()); //true
Console.WriteLine(new NumberedFlower().GetFlowerDescriptor()); //System.Int32
}
Generics have an adverse effect when it comes to reflecting over and comparing types, because a FlowerDescriptor<int> is a different type from FlowerDescriptor<string>. This is something I have not found a good rhythm for.

Explicit casting vs using 'as' inside a generic method [duplicate]

This question already has answers here:
Cast from Generics<T> to Specific SubClass
(9 answers)
Closed 7 years ago.
I have a simple interface and two classes implement it:
public interface IMovable { }
public class Human : IMovable { }
public class Animal : IMovable { }
The following generic method results in a compile-time error: Cannot convert type 'Human' to 'T'
public static T DoSomething<T>(string typeCode) where T : class, IMovable
{
if (typeCode == "HUM")
{
return (T)new Human(); // Explicit cast
}
else if (typeCode == "ANI")
{
return (T)new Animal(); // Explicit cast
}
else
{
return null;
}
}
But when the as keyword is used, all is fine:
public static T DoSomething<T>(string typeCode) where T : class, IMovable
{
if (typeCode == "HUM")
{
return new Human() as T; // 'as'
}
else if (typeCode == "ANI")
{
return new Animal() as T; // 'as'
}
else
{
return null;
}
}
Why does as work but explicit cast doesn't?
Short answer is, because T doesn't have to be of the correct type. Compiler is really trying to help you here, because you are doing something which might easily fail in runtime.
E.g. consider what happens with:
var result = DoSomething<Human>("ANI");
Longer answer is, you shouldn't be casting at all. Casting indicates problems with your OOP design, and is especially wrong when using generics: you lose the whole point of generics, actually. Generics are supposed to allow you create a "template" which abstracts away the actual type, leaving you to worry about the algorithm itself instead of concrete types.
In this case, you probably don't need generics at all. Your method is basically a less safer way of doing this:
public static T DoSomething<T>() where T : new()
{
return new T();
}
or this:
public static IMovable DoSomething(string typeCode)
{
if (typeCode == "HUM")
return new Human();
if (typeCode == "ANI")
return new Animal();
return null;
}
To silence the compiler, you may also add an intermediate cast, which tells the compiler you went an extra step to indicate that you really want to cast it this way: For example, using
(T)(object)new Human()
or
(T)(IMovable)new Human()
will both pass compilation, although the conversion from IMovable to T is no safer than the original code, and casting an object to T even unsafer. But this is not the solution to your underlying issue, which is design related.
With your code, it is perfectly possible to call DoSomething<Animal>, and then you have (Animal)new Human().
That is biologically correct, but your model does not allow it.
Do you really need generics here? Maybe you just want to return IMovable in this case.
Under the covers, the 'as' will do an 'is' check first before attempting the cast. So it will not attempt it if it can't cast it and will then return null.

Generics in C# with "as" and "is" having troubles, "is" check fails

I'm running into troubles with C# generics:
MappingAdapter is a common abstract base class that FullMappingAdapter and LiteMappingAdapter inherit from / implement.
Creating an instance of my generic class session:
session = new Session<FullMappingAdapter>(
// ...
)
In session, deciding what kind of session we are:
// class declaration:
public class Session<T> : ISession
where T : MappingAdapter {
// ...
// method body:
T t = null;
if (t is FullMappingAdapter) {
// need parameter, cannot use where T : new() above
t = new FullMappingAdapter(someData) as T;
} else if (t is LiteMappingAdapter) {
t = new LiteMappingAdapter(someData) as T;
} else {
throw new NotSupportedException("Unknown Adapter specified, please fix.");
}
// ... more methods here ...
}
I always get NotSupportedException thrown. Also, when looking at my stack in the debugger it says "FullMappingAdapter" in the "type" column of t, which is correct, and what I expected. But why doesn't the "is" keyword also recognize the type?
What am I doing wrong?
null is never anything.
You want to check typeof(T) for being exact type (or maybe IsAssignableFrom) instead.
Exact match (not the same as is FullMappingAdapter because it will not include derived types)
if(typeof(T) == typeof(FullMappingAdapter))
Assignable - same as is FullMappingAdapter:
if (typeof(FullMappingAdapter).IsAssignableFrom(typeof(T))
You should modify your check to use typeof:
if (typeof(T) == typeof(FullMappingAdapter))
and so on
You have to check like this
if (typeof(T) == typeof(FullMappingAdapter))

Return instance of generic type

I wrote a generic class and want to crate its instance from a static method. The problem is that I can’t create generic instance of the object. I know that it sounds confusing and it is better to show the code.
public class Parameter<T> : IParameter<T>
{
public string Name { get; set; }
public T Value { get; set; }
public bool IsValid()
{
if (String.IsNullOrEmpty(Name))
return false;
return (typeof(T) == typeof(String)) ||
typeof(T) == typeof(bool) ||
typeof(T) == typeof(int) ||
typeof(T) == typeof(double);
}
public XElement ToXml()
{
if (!IsValid())
throw new InvalidParameterException();
var xElement = new XElement("Parameter", Value,
new XAttribute("Type", typeof (T)),
new XAttribute("Name", Name));
return xElement;
}
public static Parameter<T> FromXml(XElement xElement)
{
var sType = xElement.Attributes()
.Where(attribute => attribute.Name == "Type")
.Single().Name.ToString();
var name = xElement.Attributes()
.Where(attribute => attribute.Name == "Name")
.Single().Name.ToString();
var sValue = xElement.Value;//need to use this
var typeVar = Type.GetType(sType);// and this to create proper instance of Parameter<T>
//I need somehow set T equal to typeVar here and Set
return new Parameter<T>() {Name = name};//this is wrong.
//I need return either Parameter<int> or Paramter<double> or Parameter<string> or Parameter<bool>
//basing on typeVar
}
}
I'm not sure if this possible at all... but looks like it is trivial object design requirement. Any ideas?
Thanks!
UPD: I'm using .NET 4.0. Does it make any difference? :)
UPD2: Looking at the problem now I see that this is a silly question. And it is impossible to return such "generic" objects.
Make a non-generic base class and inherit the generic class from it (they can have the same name and only differ by the generic type). On the non-generic base class, create generic instances in your static method (which returns the non-generic base class as result). You can then cast this to the generic type you expect.
public abstract class Parameter {
public static Parameter FromXml(XElement xElement) {
...
}
public string Name { get; set; }
public abstract XElement ToXml();
}
public class Parameter<T>: Parameter {
public T Value { get; set; }
public override XElement ToXml() {
...
}
}
There isn't really another way of doing this, since in your sample the type for T is specified before the static method runs.
The problem is: T is evaluated at compile time. The compiler does not have any chance to know, to which actual type your 'sType' will evaluate at runtime. Also, in the compiled assembly, no generics exist anymore. Therefore, in order to construct a type at runtime, based on condition which can only get evaluated at runtime, you will have to pesent the compiler a concrete type for compiling anyway. So somewhere you may decide your return type in an if .. else cascade like that:
if (sType is String)
return new Parameter<String>()
else if (sType is double)
return new Parameter<double>()
...
This may be placed inside a factory class or right near to the XElement class, I guess.
In order to be able to return Parameter for example, you may use an interface (or a common base class, like in another answer), which may stand for all Parameter variants. This is the reason, why the method, which parses the Xml IMO is better placed outside of Parameter.
Also, since it seems, you are cert of 'deserializing' from XML, consider using some de-/serializer functionality ;)
This does work for custom classes but it may not work for value types. Take a look at This Post to see how this work for heap types.
As Indicated by SLaks, this is impossible. Think of it this way,
Parameter<???> value = Parameter<???>.FromXml(...);
How will you ever resolve what the questionmarks should be when it depends on the content of the XmlElement?
You should use a common class which both captures Value as an object and exposes type information.

Categories

Resources