c# \ Generic \ use generic on variable within a function body - c#

Is it possible to use Generic mechanism within function body?
for exammple
if (!(someClass is IClass<T, G> where T : someInterface, G : anotherInterface))
{
return;
}
or do casting like this:
var v = (IClass <T, G> where T : someInterface, G: anotherInterface)something;

You can do this, but you have to make sure your interface is covariant:
interface IClass<out T, out S>
{
// Methods that can return a T or S but not accept one as input
}
By marking the type parameters as out, you are basically saying "I will only ever get a T or an S out of this interface". For example, IEnumerable<out T> as you can only get a T out of it, but only List<T> because you can put a T into a list as well as get one out.
Having defined your interface as such, an IClass<string, string> is an IClass<object, object>: you know your IClass<string, string> will only ever give you a string, but since a string is an object then that's fine, and if you assign it to an IClass<object, object> you know it will only ever give you an object.
(You can't do this if you interface allows you to put a T or an S into something. If this was the case, and you assigned your IClass<string, string> to an IClass<object, object>, you could try to put an int into it and it would fail, because the underlying class only really accepts a string.)
What this then lets you do is
if (!(something is IClass<object, object>))
{
return;
}
or
var v = (IClass<object, object>)something;
and both will work if something is actually an object that implements, say, IClass<string, string>.

For the first example, yes - you just need to specify the types:
if (!(someClass is IClass<ISomeInterface, IAnotherInterface>))
{
return;
}
The other is muct the same:
var v = (IClass <ISomeInterface, IAnotherInterface>)something;
Although its probably better to use as
var v = something as IClass <ISomeInterface, IAnotherInterface>;
if(v != null)
{
// Do something.
}
The second line above is important - by using as in place of a direct cast you wont get an InvalidCastException if it fails, but v will be null if the cast using as fails. This technique gives you a little more control over failure if your attempt to cast is invalid. (Consider why the conversion would be invalid: if that represents a situation where you know longer know what the world looks like, the InvalidCastException is probably the correct approach. If it's reasonable for the object not to be an instance of the interface, then as is your friend.)

you could try this:
if (!(someClass is IClass<someInterface, anotherInterface>)
{
return;
}
or via reflection:
var t = someClass.GetType()
Type[] typeParameters = t.GetGenericArguments();
if (!typeParameters[0].IsSubclassOf(typeof(someInterface)) ||
!typeParameters[1].IsSubclassOf(typeof(anotherInterface)))
{
return;
}

where constraints are to be applied to the generic method itself. You can use the desired types with no problem.
On a side note: don't check for false, it's more confusing on the long run.
if (someClass is IClass<someInterface, anotherInterface>)
{
// your code
}
// else { return; } // no longer needed!
Expanding and enveloping the code in a generic method, it would look like this:
void myMethod<T, U>()
where T : someInterface
where U : anotherInterface
{
if (someClass is IClass<T, U>)
{
// your code
}
// else { return; } // no longer needed!
}

Related

In c#, how do I know what subclass an object is when stored as the parent? [duplicate]

I've seen many people use the following code:
Type t = obj1.GetType();
if (t == typeof(int))
// Some code here
But I know you could also do this:
if (obj1.GetType() == typeof(int))
// Some code here
Or this:
if (obj1 is int)
// Some code here
Personally, I feel the last one is the cleanest, but is there something I'm missing? Which one is the best to use, or is it personal preference?
All are different.
typeof takes a type name (which you specify at compile time).
GetType gets the runtime type of an instance.
is returns true if an instance is in the inheritance tree.
Example
class Animal { }
class Dog : Animal { }
void PrintTypes(Animal a) {
Console.WriteLine(a.GetType() == typeof(Animal)); // false
Console.WriteLine(a is Animal); // true
Console.WriteLine(a.GetType() == typeof(Dog)); // true
Console.WriteLine(a is Dog); // true
}
Dog spot = new Dog();
PrintTypes(spot);
What about typeof(T)? Is it also resolved at compile time?
Yes. T is always what the type of the expression is. Remember, a generic method is basically a whole bunch of methods with the appropriate type. Example:
string Foo<T>(T parameter) { return typeof(T).Name; }
Animal probably_a_dog = new Dog();
Dog definitely_a_dog = new Dog();
Foo(probably_a_dog); // this calls Foo<Animal> and returns "Animal"
Foo<Animal>(probably_a_dog); // this is exactly the same as above
Foo<Dog>(probably_a_dog); // !!! This will not compile. The parameter expects a Dog, you cannot pass in an Animal.
Foo(definitely_a_dog); // this calls Foo<Dog> and returns "Dog"
Foo<Dog>(definitely_a_dog); // this is exactly the same as above.
Foo<Animal>(definitely_a_dog); // this calls Foo<Animal> and returns "Animal".
Foo((Animal)definitely_a_dog); // this does the same as above, returns "Animal"
Use typeof when you want to get the type at compilation time. Use GetType when you want to get the type at execution time. There are rarely any cases to use is as it does a cast and, in most cases, you end up casting the variable anyway.
There is a fourth option that you haven't considered (especially if you are going to cast an object to the type you find as well); that is to use as.
Foo foo = obj as Foo;
if (foo != null)
// your code here
This only uses one cast whereas this approach:
if (obj is Foo)
Foo foo = (Foo)obj;
requires two.
Update (Jan 2020):
As of C# 7+, you can now cast inline, so the 'is' approach can now be done in one cast as well.
Example:
if(obj is Foo newLocalFoo)
{
// For example, you can now reference 'newLocalFoo' in this local scope
Console.WriteLine(newLocalFoo);
}
1.
Type t = typeof(obj1);
if (t == typeof(int))
This is illegal, because typeof only works on types, not on variables. I assume obj1 is a variable. So, in this way typeof is static, and does its work at compile time instead of runtime.
2.
if (obj1.GetType() == typeof(int))
This is true if obj1 is exactly of type int. If obj1 derives from int, the if condition will be false.
3.
if (obj1 is int)
This is true if obj1 is an int, or if it derives from a class called int, or if it implements an interface called int.
Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
This is an error. The typeof operator in C# can only take type names, not objects.
if (obj1.GetType() == typeof(int))
// Some code here
This will work, but maybe not as you would expect. For value types, as you've shown here, it's acceptable, but for reference types, it would only return true if the type was the exact same type, not something else in the inheritance hierarchy. For instance:
class Animal{}
class Dog : Animal{}
static void Foo(){
object o = new Dog();
if(o.GetType() == typeof(Animal))
Console.WriteLine("o is an animal");
Console.WriteLine("o is something else");
}
This would print "o is something else", because the type of o is Dog, not Animal. You can make this work, however, if you use the IsAssignableFrom method of the Type class.
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
This technique still leaves a major problem, though. If your variable is null, the call to GetType() will throw a NullReferenceException. So to make it work correctly, you'd do:
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
With this, you have equivalent behavior of the is keyword. Hence, if this is the behavior you want, you should use the is keyword, which is more readable and more efficient.
if(o is Animal)
Console.WriteLine("o is an animal");
In most cases, though, the is keyword still isn't what you really want, because it's usually not enough just to know that an object is of a certain type. Usually, you want to actually use that object as an instance of that type, which requires casting it too. And so you may find yourself writing code like this:
if(o is Animal)
((Animal)o).Speak();
But that makes the CLR check the object's type up to two times. It will check it once to satisfy the is operator, and if o is indeed an Animal, we make it check again to validate the cast.
It's more efficient to do this instead:
Animal a = o as Animal;
if(a != null)
a.Speak();
The as operator is a cast that won't throw an exception if it fails, instead returning null. This way, the CLR checks the object's type just once, and after that, we just need to do a null check, which is more efficient.
But beware: many people fall into a trap with as. Because it doesn't throw exceptions, some people think of it as a "safe" cast, and they use it exclusively, shunning regular casts. This leads to errors like this:
(o as Animal).Speak();
In this case, the developer is clearly assuming that o will always be an Animal, and as long as their assumption is correct, everything works fine. But if they're wrong, then what they end up with here is a NullReferenceException. With a regular cast, they would have gotten an InvalidCastException instead, which would have more correctly identified the problem.
Sometimes, this bug can be hard to find:
class Foo{
readonly Animal animal;
public Foo(object o){
animal = o as Animal;
}
public void Interact(){
animal.Speak();
}
}
This is another case where the developer is clearly expecting o to be an Animal every time, but this isn't obvious in the constructor, where the as cast is used. It's not obvious until you get to the Interact method, where the animal field is expected to be positively assigned. In this case, not only do you end up with a misleading exception, but it isn't thrown until potentially much later than when the actual error occurred.
In summary:
If you only need to know whether or not an object is of some type, use is.
If you need to treat an object as an instance of a certain type, but you don't know for sure that the object will be of that type, use as and check for null.
If you need to treat an object as an instance of a certain type, and the object is supposed to be of that type, use a regular cast.
If you're using C# 7, then it is time for an update to Andrew Hare's great answer. Pattern matching has introduced a nice shortcut that gives us a typed variable within the context of the if statement, without requiring a separate declaration/cast and check:
if (obj1 is int integerValue)
{
integerValue++;
}
This looks pretty underwhelming for a single cast like this, but really shines when you have many possible types coming into your routine. The below is the old way to avoid casting twice:
Button button = obj1 as Button;
if (button != null)
{
// do stuff...
return;
}
TextBox text = obj1 as TextBox;
if (text != null)
{
// do stuff...
return;
}
Label label = obj1 as Label;
if (label != null)
{
// do stuff...
return;
}
// ... and so on
Working around shrinking this code as much as possible, as well as avoiding duplicate casts of the same object has always bothered me. The above is nicely compressed with pattern matching to the following:
switch (obj1)
{
case Button button:
// do stuff...
break;
case TextBox text:
// do stuff...
break;
case Label label:
// do stuff...
break;
// and so on...
}
EDIT: Updated the longer new method to use a switch as per Palec's comment.
I had a Type-property to compare to and could not use is (like my_type is _BaseTypetoLookFor), but I could use these:
base_type.IsInstanceOfType(derived_object);
base_type.IsAssignableFrom(derived_type);
derived_type.IsSubClassOf(base_type);
Notice that IsInstanceOfType and IsAssignableFrom return true when comparing the same types, where IsSubClassOf will return false. And IsSubclassOf does not work on interfaces, where the other two do. (See also this question and answer.)
public class Animal {}
public interface ITrainable {}
public class Dog : Animal, ITrainable{}
Animal dog = new Dog();
typeof(Animal).IsInstanceOfType(dog); // true
typeof(Dog).IsInstanceOfType(dog); // true
typeof(ITrainable).IsInstanceOfType(dog); // true
typeof(Animal).IsAssignableFrom(dog.GetType()); // true
typeof(Dog).IsAssignableFrom(dog.GetType()); // true
typeof(ITrainable).IsAssignableFrom(dog.GetType()); // true
dog.GetType().IsSubclassOf(typeof(Animal)); // true
dog.GetType().IsSubclassOf(typeof(Dog)); // false
dog.GetType().IsSubclassOf(typeof(ITrainable)); // false
I prefer is
That said, if you're using is, you're likely not using inheritance properly.
Assume that Person : Entity, and that Animal : Entity. Feed is a virtual method in Entity (to make Neil happy)
class Person
{
// A Person should be able to Feed
// another Entity, but they way he feeds
// each is different
public override void Feed( Entity e )
{
if( e is Person )
{
// feed me
}
else if( e is Animal )
{
// ruff
}
}
}
Rather
class Person
{
public override void Feed( Person p )
{
// feed the person
}
public override void Feed( Animal a )
{
// feed the animal
}
}
I believe the last one also looks at inheritance (e.g. Dog is Animal == true), which is better in most cases.
It depends on what I'm doing. If I need a bool value (say, to determine if I'll cast to an int), I'll use is. If I actually need the type for some reason (say, to pass to some other method) I'll use GetType().
The last one is cleaner, more obvious, and also checks for subtypes. The others do not check for polymorphism.
Used to obtain the System.Type object for a type. A typeof expression takes the following form:
System.Type type = typeof(int);
Example:
public class ExampleClass
{
public int sampleMember;
public void SampleMethod() {}
static void Main()
{
Type t = typeof(ExampleClass);
// Alternatively, you could use
// ExampleClass obj = new ExampleClass();
// Type t = obj.GetType();
Console.WriteLine("Methods:");
System.Reflection.MethodInfo[] methodInfo = t.GetMethods();
foreach (System.Reflection.MethodInfo mInfo in methodInfo)
Console.WriteLine(mInfo.ToString());
Console.WriteLine("Members:");
System.Reflection.MemberInfo[] memberInfo = t.GetMembers();
foreach (System.Reflection.MemberInfo mInfo in memberInfo)
Console.WriteLine(mInfo.ToString());
}
}
/*
Output:
Methods:
Void SampleMethod()
System.String ToString()
Boolean Equals(System.Object)
Int32 GetHashCode()
System.Type GetType()
Members:
Void SampleMethod()
System.String ToString()
Boolean Equals(System.Object)
Int32 GetHashCode()
System.Type GetType()
Void .ctor()
Int32 sampleMember
*/
This sample uses the GetType method to determine the type that is used to contain the result of a numeric calculation. This depends on the storage requirements of the resulting number.
class GetTypeTest
{
static void Main()
{
int radius = 3;
Console.WriteLine("Area = {0}", radius * radius * Math.PI);
Console.WriteLine("The type is {0}",
(radius * radius * Math.PI).GetType()
);
}
}
/*
Output:
Area = 28.2743338823081
The type is System.Double
*/
I found checking if the type of something is equal to something is done by the following:
variableName.GetType() == typeof(int)
if (c is UserControl) c.Enabled = enable;
You can use "typeof()" operator in C# but you need to call the namespace using System.IO; You must use "is" keyword if you wish to check for a type.
Performance test typeof() vs GetType():
using System;
namespace ConsoleApplication1
{
class Program
{
enum TestEnum { E1, E2, E3 }
static void Main(string[] args)
{
{
var start = DateTime.UtcNow;
for (var i = 0; i < 1000000000; i++)
Test1(TestEnum.E2);
Console.WriteLine(DateTime.UtcNow - start);
}
{
var start = DateTime.UtcNow;
for (var i = 0; i < 1000000000; i++)
Test2(TestEnum.E2);
Console.WriteLine(DateTime.UtcNow - start);
}
Console.ReadLine();
}
static Type Test1<T>(T value) => typeof(T);
static Type Test2(object value) => value.GetType();
}
}
Results in debug mode:
00:00:08.4096636
00:00:10.8570657
Results in release mode:
00:00:02.3799048
00:00:07.1797128

Cannot convert Type `ClassA` to T

I'm writeing a generice method in C#:
private T GetMamConfigurations<T>(IDictionary<string, object> items,
MaMDBEntities maMDBEntities) where T : class
{
T geoConfigs = default(T);
if (typeStr.Equals("MamConfiguration", StringComparison.OrdinalIgnoreCase))
{
geoConfigs = (T)GetGeoConfigurationNumericFromDB(items, maMDBEntities);
}
else if (typeStr.Equals("ListOfMamConfiguration", StringComparison.OrdinalIgnoreCase))
{
geoConfigs = (T)GetGeoConfigurationsPercentageFromDB(items, maMDBEntities);
}
return geoConfigs;
}
GetGeoConfigurationNumericFromDB returns MamConfiguration
whereas
GetGeoConfigurationsPercentageFromDB returns IList<MamConfiguration>
and I get compliation error:
cannot cast expression of type MamConfiguration to type T
Why is that?
Is there any way to solve without forcinf the two methods to return IList<MamConfiguration> ?
Well, you can always placate the compiler by adding an object cast in the middle:
geoConfigs = (T)(object)GetGeoConfigurationNumericFromDB(items, maMDBEntities);
which will defer the type-check until runtime. However! There is no compiler way to do this otherwise, as it is never going to be happy with string tests like "MamConfiguration". Also, generics work well when the code is ... generic - i.e. does the same thing which each type. The code shown is the opposite of generic. It is non-generic code exposed through a generic API. It is always going to be messy inside. Personally I would try to avoid this usage in the first place.
Instead of using (T) to cast to T, you can use the as operator. as will return null if the conversion fails. If it succeeds, it will return your converted value.
geoConfigs = GetGeoConfigurationNumericFromDB(items, maMDBEntities) as T;

Convert a Type to a Generic constrained T

I am trying to build a Factory which will supply a single factory method.
In this method I want to verify whether the incoming Type is the factory's T.
What I've written is simply not working. I believe I understand the reason for it's failure, yet I am not sure how to form my casting correctly.
Below is my code. Any ideas as for how to form this condition/casting?
public T GetFeature(Type i_FeatureType, User i_UserContext)
{
T typeToGet = null;
if (i_FeatureType is T) // <--condition fails here
{
if (m_FeaturesCollection.TryGetValue(i_FeatureType, out typeToGet))
{
typeToGet.LoggenInUser = i_UserContext;
}
else
{
addTypeToCollection(i_FeatureType as T, i_UserContext);
m_FeaturesCollection.TryGetValue(typeof(T), out typeToGet);
typeToGet.LoggenInUser = i_UserContext;
}
}
return typeToGet;
}
Use:
if (typeof(T).IsAssignableFrom(i_FeatureType))
Instead of:
if (i_FeatureType is T)
You are comparing your objects with a 'Type' object.
So, instead of
if (i_FeatureType is T)
try
if (i_FeatureType == typeof(T))

Getting correct return value on a method call using reflection

I have the following generic method inside my class that works as a repository pattern:
public DbSet<T> GetAll<T>() where T : class
{
return dbContext.Set<T>();
}
Now, i would like to get a list of all entities in the database that belong to an entity class that implements a specific interface (IChangeTrackingEntity). So currently there are around 10 specific tables/classes that conform to this, but i don't want to add 10 hardcoded calls to these tables, so I would like to do it using reflection instead (it might also be that the classes that implement this interface change in the future and I don't want to have to remember to change here as well and make the code dependant on each other).
Example of code that works, but that i don't want:
var result = new List<IChangeTrackingEntity>();
using ( var repository = new DbRepository())
{
result.AddRange( repository.GetAll<FirstTypeThatImplementsInterface>() );
result.AddRange( repository.GetAll<SecondTypeThatImplementsInterface>() );
result.AddRange( repository.GetAll<ThirdTypeThatImplementsInterface>() );
result.AddRange( repository.GetAll<FourthTypeThatImplementsInterface>() );
result.AddRange( repository.GetAll<FifthTypeThatImplementsInterface>() );
}
return result;
I am quite close, but I can't get the last part to work of casting the result of the Invoke back to the correct type. Waht i got currently is this:
var result = new List<IChangeTrackingEntity>();
var method = typeof (DbRepository).GetMethod("GetAll");
using ( var repository = new DbRepository())
{
foreach (var p in typeof(AnchorDbContext).GetProperties())
{
if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
{
var pType = p.PropertyType.GetGenericArguments()[0];
if (pType.GetInterface("IChangeTrackingEntity") != null)
{
var genericMethod = method.MakeGenericMethod(new[] {pType});
result.AddRange(genericMethod.Invoke(repository, null) as DbSet<IChangeTrackingEntity>);
}
}
}
return result;
}
The problem above it that the Invoke call return a object and I need to cast it to basically DbSet<pType>.
In my current code genericMethod.Invoke(repository, null) as DbSet<IChangeTrackingEntity> returns null indicating that I can't cast the return value as I want, so I need the specific return value type and not the interface I think.
Any idea of how to accomplish this?
Try casting to IEnumerable<IChangeTrackingEntity>. This should work due to co/contravariance.
I don't know much about this specific issue, but you seem to be casting from DbSet<T> where T : IChangeTrackingEntity to DbSet<IChangeTrackingEntity>. This is called covariance or contravariance (I always get confused between them...) and it only works if DbSet<> is an interface. So, casting won't work here. Use an equivalent interface if you can, or make a generic method that accepts DbSet where T: IChangeTrackingEntity and returns DbSet<IChangeTrackingEntity> somehow. I'll try to work out how to do that, and post an answer, if no one has answered before me (unlikely on this site :P)
I'm thinking you need to see this question:
MethodInfo method = typeof(Sample).GetMethod("GenericMethod");
MethodInfo generic = method.MakeGenericMethod(myType);
generic.Invoke(this, null);

C#: How can I use implicit cast operator during object to type conversion?

HI!
Here is my case: I have some value type which is wrapped into another type with appropriate implicit converters. If I cast wrapped type to an object and then try to get original value I can do that in two-step cast only.
If simplified my code is as follows:
public enum MyEnum : int
{
First,
Second
}
public class Test<T>
{
public Test(T val)
{
Value = val;
}
private T Value { get; set; }
public static implicit operator T(Test<T> m)
{
return m.Value;
}
public static implicit operator Test<T>(T m)
{
var res = new Test<T>(m);
return res;
}
}
static void Main()
{
object res = new Test<MyEnum>(MyEnum.First);
Console.WriteLine((MyEnum)(Test<MyEnum>)res);
Console.WriteLine((MyEnum)res);
}
First "Console.WriteLine" works OK. Second one fails.
Is there any way I can modify this behavior and get it working without double casting?
UPDATE 1
I must use object to value cast (in real application I have to cast ComboBox.SelectedItem property and I do not want to add extra property to ComboBox, because I'll have to change my UI interaction code everywhere).
UPDATE 2
Implicit conversions to and from System.Object are not allowed.
UPDATE 3
Updated my sample code to reflect the whole problem.
Don't use object that way. Write your first line like this instead:
Test res = new Test(1);
If you must have it in an object first, remember that all the compiler knows about it at this point is that it's an object, and nothing more. You, as the programmer, have additional information about what you expect this object to be, but for the compiler to take advantage of that information you have to put it into your code somewhere.
Update:
I'm glad I was able to find this again, because this almost-very-timely article by Eric Lippert, who works on the C# language design, went up this morning and explains the problem in depth:
http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx
If you want to simplify casting and not care performance effect, then create extension method.
public static T To<T>(this object obj) {
Type type = obj.GetType();
MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
MethodInfo method = methods.FirstOrDefault(mi => (mi.Name == "op_Implicit" || mi.Name == "op_Explicit") && mi.ReturnType == typeof(T));
if (method == null)
throw new ArgumentException();
return (T)method.Invoke(null, new[] { obj });
}
Usage
Console.WriteLine(res.To<MyEnum>());
Instead of adding implicit operators, consider implementing IConvertible. You only need to implement the ToInt32 method, the others are meaningless and you can throw the InvalidCastException in the other methods.
After that, you can use Convert.ToInt32() method to convert your object in one step.
or even
var res = new Test(1);
Your local variable res is always of type object; so the line that isn't working is trying to convert an object, that isn't an int, to an int, which can't be done. Same as this fails:
object d = 5.5d;
Console.WriteLine((int)d);
EDIT:
Perhaps a pattern that might help is something like this:
if (res.GetType() == typeof(Test))
{
Console.WriteLine((int)(Test)res);
}
else
{
Console.WriteLine((int)res);
}
It's a very localized solution to your problem, but perhaps it will work for you.
While the error is due to res being of type object, I would make the Test->int operator explicit...

Categories