The documentation isn't very clear about execution time of nameof
, but you can find the following sentence:
Unfortunately typeof is not a constant expression like nameof
We also have the specification in the C# language repository which states:
A nameof_expression is a constant expression of type string, and has no effect at runtime.
It's a reason why nameof(T)
returns "T"
and not the actual type name in your case. Therefore you need another way to obtain the type name at runtime. It's the typeof
operator. From the specification:
The typeof operator can be used on a type parameter. The result is the System.Type object for the run-time type that was bound to the type parameter.
class Shape { }
class Circle : Shape { }
class Program
{
// Output of the following code is Circle
static void Main(string[] args) => WriteType<Circle>();
static void WriteType<T>() where T : Shape => Console.WriteLine(typeof(T).Name);
}
As you can see the result fully depends on the bound type of the WriteType<T>
method. This means if the bound type is Shape
then "Shape"
would be printed. Therefore when you iterating over a collection of Shape
's the bound type of T
would be Shape
and not Circle
. It's because T
is deduced as Shape
.
static void Main(string[] args)
{
var shapes = new Shape[] { new Circle() };
foreach (var shape in shapes)
WriteBoundType(shape);
// Output is "Shape"
}
static void WriteBoundType<T>(T shape)
where T : Shape => Console.WriteLine(typeof(T).Name);
If you want to obtain the runtime type of the current shape then you should use the GetType
method. From the typeof
operator documentation:
To obtain the run-time type of an expression, you can use the .NET Framework method GetType, as in the following example
It's your case. You need neither typeof
nor nameof
. You do not need even generics because you want the runtime type of the current instance.
public AddShape(Shape shape)
{
dict.Add(shape.GetType().Name, shape.SerializableShape);
// You also can use the result of GetType directly or its FullName.
// It depends on your demands which we don't know well.
}
You failed because you have worked with C++ which is statically typed too, but there is a difference. As you know in C++ template arguments are substituted at compile time, but in .NET they are substituted at runtime. I would recommend you to read Differences Between C++ Templates and C# Generics.