What does T stands for in C#? [duplicate] - c#

This question already has answers here:
What does "T" mean in C#?
(7 answers)
Closed 9 years ago.
public void DisplayValue<T>(T field, string fieldname)
What does T stands for in above code?
Whats the benefit to do so?
Where we can use this?

From Generics (C# Programming Guide)
... by using a generic type parameter T you can write a single class
that other client code can use without incurring the cost or risk of
runtime casts or boxing operations

It is a Generic Type Parameter.
A generic type parameter allows you to specify an arbitrary type T to a method at compile-time, without specifying a concrete type in the method or class declaration.
For example:
public T[] Reverse<T>(T[] array)
{
var result = new T[array.Length];
j=0;
for(int i=array.Length; i>= 0; i--)
{
result[j] = array[i];
j++;
}
return result;
}
reverses the elements in an array. The key point here is that the array elements can be of any type, and the function will still work. You specify the type in the method call; type safety is still guaranteed.
So, to reverse an array of strings:
string[] array = new string[] { "1", "2", "3", "4", "5" };
var result = reverse(array);Will produce a string array in result of { "5", "4", "3", "2", "1" }
This has the same effect as if you had called an ordinary (non-generic) method that looks like this:
public string[] Reverse(string[] array)
{
var result = new string[array.Length];
j=0;
for(int i=array.Length; i >= 0; i--)
{
result[j] = array[i];
j++;
}
return result;
}The compiler sees that array contains strings, so it returns an array of strings. Type string is substituted for the T type parameter.
Generic type parameters can also be used to create generic classes.
In the example you gave of a SampleCollection, the T is a placeholder for an arbitrary type; it means that SampleCollection can represent a collection of objects, the type of which you specify when you create the collection.
So:
var collection = new SampleCollection<string>();
creates a collection that can hold strings. The Reverse method illustrated above, in a somewhat different form, can be used to reverse the collection's members.

Type Parameters T: The type of elements in the list.
according to MSDN documentation.
Whats the benefit to do so?
The method can take anonymous lists of a type.
Where we can use this?
For example when the same manipulation has to be done on several lists of several types.

Related

C#: Why does dynamic help determine type argument for use in generic methods?

I'm working with reflection to create some meta-tests to ensure equality between two instances of the same type.
As such, I'm using a lot of vars and generics.
One thing I've noticed is that with my generic functions, sometimes the Type argument is object (presumably when it can't determine the type) and other times it's the correct type.
Example:
Generic methods
public static RT[] CreateArrayWithNumItems<RT>(RT baseArgument, int numItems)
{
var a = new List<RT>();
for (int i = 0; i < numItems; i++)
a.Add((RT)DataObjectCreator.CreateUninitializedObject(typeof(RT)));
return a.Select(x => (RT)x).ToArray();
} //actual implementation more complex
private static T UnboxObject<T>(T boxedObject)
=> boxedObject;
public static object CreateUninitializedObject(Type typeObject)
=> typeObject == typeof(string) ? "" : FormatterServices.GetUninitializedObject(typeObject);
Use of methods:
var a = Model.GetType();
var unitializedObject = CreateUninitializedObject(a); //returns typed object
var objectArray = CreateArrayWithNumItems(unitializedObject, 1); //returns object array
var uob = UnboxObject(unitializedObject); //returns typed object
var uobObjectArray = CreateArrayWithNumItems(uob, 1); //returns object array
var typedArray = CreateArrayWithNumItems((dynamic) unitializedObject, 1); //returns typed object array
This seems strange to me (a.k.a I'm missing some knowledge), so I have a few questions about it.
Given the same variable, why does UnboxObject return a typed object and CreateArrayWithNumItems return an array of object?
Given the typed object uob why does CreateArrayWithNumItems return an array of object?
Lastly (and most importantly), why does casting to dynamic prior to calling CreateArrayWithNumItems allow the generic method to determine the type?
Without dynamic, the compiler performs all the type evaluations based on static analysis; assuming that CreateUninitializedObject returns object (presumably via FormatterServices), the call to CreateArrayWithNumItems infers the generic type parameters based on that static type, i.e.
var objectArray = CreateArrayWithNumItems(unitializedObject, 1);
becomes
var objectArray = CreateArrayWithNumItems<object>(unitializedObject, 1);
precisely because unitializedObject is object.
With dynamic, the runtime performs the work, but now it has knowledge of the actual object at runtime, so it knows that the type is (whatever Model is). The runtime then constructs something like:
dynamic objectArray = CreateArrayWithNumItems<TheActualType>((TheActualType)unitializedObject, 1);
(how it actually does it is much more complex; it could look for non-generic methods too, for example)
So yes, using dynamic can be a sneaky way to go from reflection (object/Type) code to strongly-typed generic code, but: it has a cost: dynamic involves more work at runtime - additional reflection, and additional runtime IL emit. You also need to be aware that typedArray is now also dynamic (unless you cast it to something else), so everything you do with typedArray becomes dynamic. Increasing costs.

why can't I create a list<T> of anonymous type in C#?

I am new to anonymous types in c#, and I want to create a list of anonymous types that contain 3 variables: string str, int num, DataTime time.
however, when I try to use the code from this question`s answers: A generic list of anonymous class
it won't work for me.
I used a simple Console application to do it and I think I get the error
because I don't have System.Core because someone in the comment of the question above said that:
(You also need a reference to System.Core of course.)
and I don't know what is System.Core and if I have it so it might be the problem
I do use Systme.Linq.
here is the code:
var list = new[] { str, num, time }.ToList();
list.add("hi", 5, DateTime.Now);
Console.WriteLine(list[0].num);
I also face issues when I try to specify the type of the variables
for example string str.
You are missing some syntax. Anonymous types must be declared with new{...}. The property names must be declared when they cannot be inferred by a variable name. (You also have a typo in Add; it should be uppercase).
The below works:
var str = "string";
var num = 5;
var time = DateTime.UtcNow;
// notice double "new"
// property names inferred to match variable names
var list = new[] { new { str, num, time } }.ToList();
// "new" again. Must specify property names since they cannot be inferred
list.Add(new { str = "hi", num = 5, time = DateTime.Now });
Console.WriteLine(list[0].num);
With that said, this is pretty clunky. I'd suggest writing a class with the properties you want, or using ValueTuple.
This works and is clearer/cleaner:
var list = new List<(string str, int num, DateTime time)>();
// ValueTuple are declared in parens, method calls require parens as well
// so we end up with two sets of parens, both required
list.Add((str, num, time));
list.Add(("hi", 5, DateTime.Now));
Console.WriteLine(list[0].num);
Another reason to prefer your own class or ValueTuple is that you cannot declare a method as accepting an anonymous type. In otherwords, something like this is not valid:
public void DoSomethingWithAnonTypeList(List<???> theList ) { ... }
There is nothing* I can put to replace the ??? as anonymous types are both internal and have "unspeakable" names. You wouldn't be able to pass your list around and do something meaningful with it. So what's the point?
Conversely, I can declare a method as accepting a list of ValueTuples:
public void DoSomethingWithTupleList(List<(string, int, DateTime)> theList) {
Console.WriteLine(theList[0].Item1);
}
or using named tuples:
public void DoSomethingWithTupleList(List<(string str, int num, DateTime time)> theList) {
Console.WriteLine(theList[0].time);
}
* You can technically pass your list of anonymous types to a generic method. However you won't be able to access the individual properties. The best you'd be able to do is access the list's Count or iterate over the list/enumerable and perhaps print the default ToString which doesn't really get you much either. There's not a generic constraint to help here. The third statement in this method will generate a compiler error:
public void DoSomethingGenerically<T>(List<T> theList) {
Console.WriteLine(theList.Count); // valid
Console.WriteLine(theList[0]); // valid, prints default ToString
Console.WriteLine(theList[0].num); // invalid! What's the point?
}
var list = new[] { new { str = "hi", num = 5, time = DateTime.Now } }.ToList();
// valid due to type inference, but see comments above
DoSomethingGenerically(list);
Do note that you'll have the same issue with ValueTuple, I'm just clarifying my "do nothing" statement.

Why compiler does not allow us to use `var` instead of `generic type`?

In the example code below Generic Type is used in writing a Reverse function that reverses an array of any type:
public T[] Reverse<T>(T[] array)
{
var result = new T[array.Length];
int j=0;
for(int i=array.Length; i>= 0; i--)
{
result[j] = array[i];
j++;
}
return result;
}
However, I could write the same code like below by using var type:
public var[] Reverse(var[] array)
{
var result = new var[array.Length];
int j=0;
for(int i=array.Length; i>= 0; i--)
{
result[j] = array[i];
j++;
}
return result;
}
However, the compiler does not accept the latter. I want know to the difference between Generic type and var?
It doesn't compile, so it doesn't work.
The use of generics and the var are very different. var means "compiler, I'm lazy, please discover for me the single exact type that I should use here, inferring it from what I'm writing after the =" (there are some cases where it is mandatory to use var instead of writing explicitly the variable type, but we will ignore them) ... So for example
var foo = "Hello";
The foo variable type is string, because the compiler can infer it by looking at the type of the expression after the assignment =. The var is totally replaced by the "correct" type in the compiled program.
So it would be equivalent to writing:
string foo = "Hello";
Generics instead are a way to make a method/class able to adapt to different types that are used in calling/creating them. In this instance the caller could
int[] foo1 = Reverse(new int[] { 1, 2, 3, 4, 5);
or
long[] bar1 = Reverse(new long[] { 1, 2, 3, 4, 5);
The compiler (because generics are resolved at compile time) will infer the type T (int or long) from the parameters used and will write it somewhere (in the compiled file). The runtime then will see this and create two different specialized versions of Reverse (one for int and one for long). But in this case T is an "openness" to the various possible types of parameters. In the case of var, there is a single possible type that the variable can be. So in the compiled file there is a Reverse<T> compiled method, while at runtime there are a Reverse<int> version of the method and a Reverse<long> version of the method (and if necessary the runtime will create other versions of the method).
Using var as a parameter wouldn't have any meaning, and it would be a poorer syntax than the generics one, where the list of used generics are put somewhere (between the method name and the ( in this case) and you can have multiple generic types, like
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
(that is the LINQ Select) where there are two generic parameters TSource and TResult. With your syntax you wouldn't be able to differentiate between the two generic parameters (there is a single var keyword), and you couldn't use var as is currently used (compiler, I'm lazy, please discover for the the type of this local variable).

Why can't I convert an object (which is really object[]) to string[]?

I have a field that is of type 'object'. When I inspect it within the Watch window of visual studio I see its Object[] and when I drill into the elements I see each element is a string.
But when I try to cast this to a String[] I get this error:
Cannot cast 'MyObject' (which has an actual type of 'object[]') to 'string[]' string[]
Any reason why I can't do this cast? What is the best way to convert this object to a string array?
This is a particularly confusing feature of C#. Here's the deal.
Throughout this discussion we assume that the element type of an array is a reference type, not a value type.
C# supports unsafe array covariance. That means that if you have an array of string, you can convert it to an array of object, because a string can be converted to an object:
string[] a1 = { "hello", "goodbye" };
object[] a2 = a1; // Legal
If you then try to get an element out of a2, it works:
object o3 = a2[0];
That's legal because a2[0] is really a1[0], which is a string, which is convertible to object.
However, if you attempt to write to the array then you'll get an error at runtime:
a2[0] = new object();
This fails at runtime because a2 is really an array of strings, and you can't put a non-string into an array of strings.
So C# is already horribly broken; it is possible to write a program that compiles and looks normal but suddenly crashes with a type exception at runtime because you tried to put an object into an array of objects that is not actually an array of objects.
The feature you want is even more broken than that, and thank goodness C# does not support it. The feature you want is:
object[] a4 = { "Hello" };
string[] a5 = a4;
That would be unsafe array contravariance. It breaks horribly like this:
a4[0] = new Customer(); // Perfectly legal
string s6 = a5[0];
And now we just copied a Customer into a variable of type string.
You should avoid any kind of array covariance or contravariance; array contravariance is, as you've discovered, not legal, and array covariance is making little time bombs in your program that go off unexpectedly. Make your arrays of the right type to begin with.
string[] newarr = Array.ConvertAll(objects, s => (string)s);
--EDIT--
since you've said I have an object (knowing that it is an object[] actually)
string[] newarr = Array.ConvertAll((object[])objects, s => (string)s);
object[] original = new object[]{"1", "2"};
//some code in between here
object obj = original ;
object[] objArray = (object[])obj;
string[] newArray = new string[objArray.Length];
for(int i = 0; i < newArray; i++)
{
newArray[i] = (string)objArray[i];
}
Other answers here are showing you quicker/shorter ways of doing the conversion. I wrote the whole thing out like this because it shows what's really going on and what needs to happen. You should use one of the simpler methods in your actual production code.
The rule in object oriented programming is -
"Derived class can always be type casted to base class" AND
"A Base class can be casted to derived class only if the current instance that base class hold off is actually derived class"
e.g. (A is base and B is derived)
A a = new B(); // legal;
B b = (B) a ; // legal as "a" is actually B (in first statement)
illegal : >
A a = new A();
B b = (B) a; // not legal as "a" is A only.
Same thing is applied to Object and String classes. Object is base class and string is Derived class.
You can convert the real string[] to object[].
This is a Array covariance
Can find a clear example in link.
You should cast each element in the collection and not the collection itself.
object[] ovalues = new object[] { "alpha", "beta" };
string[] svalues = ovalues.Cast<string>().ToArray();

C#: Generic list of enum values

Is there a way to create a method that gets an enum type as a parameter, and returns a generic list of the enum underlying type from it's values, no matter if the underlying type is int\short byte etc'...
I saw this answer of Jon Skeet, but it looks way too complicated.
If you want to pass in a Type, it can't really be usefully generic - you'd have to return a single type that isn't directly related to the input, hence something like:
public static Array GetUnderlyingEnumValues(Type type)
{
Array values = Enum.GetValues(type);
Type underlyingType = Enum.GetUnderlyingType(type);
Array arr = Array.CreateInstance(underlyingType, values.Length);
for (int i = 0; i < values.Length; i++)
{
arr.SetValue(values.GetValue(i), i);
}
return arr;
}
This is a strongly-typed vector underneath, so you could cast that to int[] etc.
While Marc's answer isn't wrong its somewhat unnecessary.
Enum.GetValues(type) returns a TEnum[] so this method is kind of unnecessary as if you know the underlying type you can just cast TEnum[] to its underlying type array.
var underlyingArray = (int[])Enum.GetValues(typeof(StringComparison));
is valid C# that will compile and won't throw an exception at runtime. Since you wanted a list once you have the array you can pass it to the List<Tunderlying> constructor or you can just call the ToArray() extension method.
Edit: you could write the function as such::
public static TUnderlying[] GetValuesAs<TUnderlying>(type enumType)
{
return Enum.GetValues(enumType) as TUnderlying[];
}
But then you would have to know the underlying type first.

Categories

Resources