Regarding generic Where T - c#

void LoadParameters<T, TValue>(TValue strategy)
where T : Parameters
Saw a code like this. Will the program still work correctly without the where statement?

If it compiles without the where statement, it will work correctly. However, chances are the coder did not simply put it there without reason. If you remove it, it will likely not compile and hence not work.

That where clause is called a "generic type constraint". Usually T can be any type and you must write your generic code with that in mind. By constraining T to be, inherit or implement a specific type, you gain the ability to refer to the members of that type in your generic code, because the compiler is assured that any object used will be that type. You can also use class, struct or new as generic type constraints, which enforce T being a reference type, a value type or having a parameterless constructor respectively.

Related

Using nameof for a recursive generic type's property

I have the following class
public abstract class Result<TResult, TData> where TResult : Result<TResult, TData>
{
public virtual TData Data { get; private set; }
}
How can I use nameof on the Data property?
It tried some options but got compilation errors
nameof(Result<object, object>.Data)
Error CS0311
The type 'object' cannot be used as type parameter 'TResult' in the generic type or method
'Result<TResult, TData>'. There is no implicit reference conversion from 'object' to
'Result<object, object>'
UPDATE
To better specify:
I did not write the class in the first snippet, but I have to use it as it is.
I need to use reflection to get a PropertyInfo instance for the Data property. I can do it by calling GetProperty("Data"), but I prefer to avoid strings in case the name property is renamed with the Visual Studio Refactoring (for example from Data to Content).
I cannot use nameof(Data) and I am in a different context that doesn't know about the Data property in that class.
As such, I would call GetProperty(nameof({whatever}.Data)). Of course, if not possible I would use the string. But if there is a way, I would like to know it.
Unfortunately, the nameof operator does not work with unbound generic types. E.g. you'd like to be able to write nameof(Result<,>.Data), just like you can today write something like typeof(Result<,>). So you would need to specify type parameters when trying to get the nameof(Result<TResult, TData>.Data) value.
Which you've tried, but you provided object as the type parameter for both parameters, even though your generic type constrains TResult as being derived from Result<TResult, TData>. The type object doesn't meet the constraint, so that can't possibly work. Hence the compiler error.
Obviously, if you can provide any type that does meet the constraint, that would solve the compiler error and allow you to use the nameof operator. There's not enough information in your question to know whether that's an option in your specific scenario.
I agree with this comment that you would probably be better off asking a different question, one which takes a step back and explains how you arrived at feeling you needed this syntax in the first place. It's not clear what the broader goal you're trying to accomplish is, where you don't have known type parameters to use for this expression. Typically, code outside of the generic type that wants to make use of the generic type, would actually know the type parameters it intends to use with the generic type.
Note that in the context of the generic type itself, you can refer to the property without knowing the exact type parameters, since the property identifier does not need qualification. E.g. nameof(Data) would work, for any code that's actually in the generic class Result<TResult, TData>. Whether that helps in your specific scenario is unclear from the information provided so far.

Nested generics <T1<T2>>

Why it is impossible to write something like this:
T1<T2> Method<T1, T2>(T1<T2> genericValue) { ... }
For example, I want to write an extension method which accepts a generic object, containing a generic colletion:
Container<CT<T>> ExtensionMethod<CT, T>(Container<CT<T>> value) { ... }
where CT can be Array, List or any other collection type and T is any type. But Compiler says "Type parameter T1 does not have type parameters".
Is there any workaround for that?
This is not possible. Your generic has to compile for any T. So if you make any assumption about T other than it being object you have to add constraints with the where keyword.
This constraints system is not very complex. You cannot add a constraint asking for T to be a class with exactly one generic type parameter. So what you want to do is impossible with the current toolset.
You would need to ask Microsoft why they did not implement it, but it appears they saw not enough business value.
Maybe you could ask a question how to implement something, without breaking it down to generics. It seems you may have an XY Problem.

nameof() operator for property of generic class [duplicate]

I am trying to get the name of a method on a generic interface. I would expect this to work as the type part would be a valid typeof:
//This does not compile
nameof(IGenericInterface<>.Method)
//This would compile
typeof(IGenericInterface<>)
I think this should be valid c#-6.0 or am I missing something or is there a better way to do this. I don't want to use a string for the Method name as if the method is renamed code would break without any build-time errors.
This is expected. According to the documentation, your expression is disallowed, because it refers to an unbound generic type:
Because the argument needs to be an expression syntactically, there are many things disallowed that are not useful to list. The following are worth mentioning that produce errors: predefined types (for example, int or void), nullable types (Point?), array types (Customer[,]), pointer types (Buffer*), qualified alias (A::B), and unbound generic types (Dictionary<,>), preprocessing symbols (DEBUG), and labels (loop:).
You can work around this limitation by supplying a generic parameter:
nameof(IGenericInterface<object>.Method)
Note: I think Microsoft should tweak nameof feature to allow references to methods of unbound generic types.
Just use a sample type in order to compile.
string name = nameof(IGenericInterface<int>.Method) // will be Method
The solutions presented with "sample types" will work, but sooner or later you will need to get the nameof a generic type which has type constraints, so nameof(MyGenericType<object>) won't work, because object does not abide by the constraints.
If you find yourself in this situation, it might seem that you have to declare a dummy little class real quick which abides by the constraints so that you can get its nameof, but having to do something as hacky as that is a clear indication that you are down the wrong rabbit hole.
Here is a better solution:
typeof(MyGenericType<>).Name
Interestingly enough, C# allows us to use <> in typeof but not in nameof. Go figure.

Cast object into appropriate type for overloaded methods

Say I have a method that is overloaded such as void PrintInfo(Person) and void PrintInfo(Item), and so on. I try to invoke these methods by passing in an Object.
I'm wondering why it is giving me an error when I do this; aren't all classes inherited from Object? I want to avoid doing an if/switch statement where I check which type the Object is before calling the appropriate method.
What do you guys think is the best approach in this case?
All Persons are objects , but not all objects are Persons. Because of this you can pass a Person to a method that accepts an object but you can't pass an object to a method that requires a Person.
It sounds like you have some common bit of functionality between various objects that you want to use. Given this, it would be best to find either a common ancestor that has all of the functionality that you need, or an interface that they all implement (that again provides everything that you need).
In the case of printing, you may just need the ToString method. In that case, you can just have the method accept an object and call ToString on it. (That's what many print methods do, such as Console.WriteLine.
You need to understand that because C# is a statically typed language (barring dynamic) the particular overload that is chosen (called overload resolution) is determined at compile time, not run time. That means that the compiler needs to be able to unequivocally determine what type your argument is. Consider:
Object foo;
foo = "String";
foo = 5;
PrintInfo(foo); // Which overload of printinfo should be called? The compiler doesn't know!
There are a few ways to solve this- making foo of type dynamic is one- that will cause the correct overload to be chosen at compile time. The problem with that is that you lose type safety- if you don't have an appropriate overload for that type, your application will still compile but will crash when you try to print the unsupported type's info.
An arguably better approach is to ensure that foo is always of the correct type, rather than just Object.
As #Servy suggests, another approach is to attach the behavior to the type itself. You could, for instance, make an interface IHasPrintInfo:
public interface IHasPrintInfo { String PrintInfo { get; } }
and implement that interface on all items whose info you might print. Then your PrintInfo function can just take an IPrintInfo:
public void PrintInfo(IPrintInfo info) {
Console.WriteLine(info.PrintInfo);
}
here its ambiguate for compiler; compiler can't figure out which version of method (Person/Item) you are intended to call.

Instantiation with C# "dynamic" Keyword

I've seen many examples of this tool which abstracts away the cumbersome syntax of Reflection. However none demonstrate instantiation of an unknown type. Is it safe to assume this isn't possible with "dynamic"?
Logically, it's impossible to instantiate an unknown type -- to instantiate a type, something must know what it is.
dynamic is useful for manipulating values of an unknown type (by assuming that it is capable of certain operations, which will fail at runtime if they are in fact not possible). To instantiate any type, however, you either need to use compile-time instantiation (e.g. using a C# constructor call), or else you need an instance of Type that corresponds to your desired type.
The compiler can use the dynamic keyword so that the dlr will construct a type, but it's designed to late bind the arguments of a constructor rather than the type to be constructed. The opensource framework ImpromptuInterface abstracts the dlr calls, including the constructor. If you need to call a constructor that has arguments this will run about 5 times faster than using reflection/Activator.
var x = Impromptu.InvokeConstructor(Type.GetType("SomeType"),args...);
I don't know what your goal is... but do you mean something like
dynamic X = Type.GetType("SomeUnknownType").GetConstructor(null).Invoke(null);
?
the above just calls the default (parameterless) constructor of the Type "SomeUnknownType" and assign the resulting instance to a dynamic .

Categories

Resources