.net 当编译时一切都是已知的时候,为什么我不能用泛型来使用nameof呢?

wbrvyc0a  于 2022-11-26  发布在  .NET
关注(0)|答案(5)|浏览(150)
public void Test<T>()
{
    Console.WriteLine(nameof(T));
}

Test<int>();

这段代码实际上打印了T而不是int,这一点用处都没有。我希望获得一个实际使用的泛型类型参数的名称,而不使用反射(typeof,然后对Type变量进行操作,等等)。
我读到泛型的要点是在编译时用不同的类型定义代码的变体。nameof也是一个编译时操作符。在这种情况下,知道T是int就足够了。除了必须从用户端完成之外,肯定还有其他方法来完成(例如Test<int>(nameof(int))
如果有人对这个用例感兴趣,除了调试之外,我还想用项目的类名作为关键字来向字典中添加一些东西。这个字典正好有每个形状的一个。

public AddShape<T>(T shape) where T : Shape
{
    dict.Add(nameof(T), shape.SerializableShape);
}
qlfbtfca

qlfbtfca1#

nameof结构用于在编译时确定一个类型、变量、字段等的 name。当你在运行时需要一个 type 时,它没有帮助。你可以做的只是使用对象的类型信息:

public AddShape<T>(T shape) where T : Shape
{
    dict.Add(shape.GetType().FullName, shape.SerializableShape);
}
soat7uwm

soat7uwm2#

因为nameof在编译时使用类型信息,并将使用该信息中的名称作为字符串,但对于泛型类型T,编译器无法在编译时计算出这一点,因为它将作为参数传递,从那里它将被使用,因为它可以是Shape或它的任何子类型,这就是它将在运行时初始化的原因,所以这就是为什么不能像上面那样使用它的原因。
我还发现这也将有助于相关:
https://stackoverflow.com/a/29878933/1875256
希望能有所帮助

sz81bmfz

sz81bmfz3#

documentationnameof的执行时间不是很清楚,但是可以找到下面的句子:
不幸的是,typeof不是像nameof那样的常量表达式
我们在C#语言存储库中也有规范,其中规定:
nameof_expression是字符串类型的常量表达式,在运行时不起作用。
这就是为什么nameof(T)返回"T"而不是实际的类型名的原因。因此,您需要另一种方法在运行时获得类型名。这就是typeof操作符。根据规范:
typeof运算子可以用在型别参数上。结果是系结至型别参数之执行阶段型别的System.Type对象。

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);
}

正如您所看到的,结果完全取决于WriteType<T>方法的绑定类型。这意味着如果绑定类型是Shape,则将打印"Shape"。因此,当您迭代Shape的集合时,T的绑定类型将是Shape而不是Circle。因为T被推导为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);

如果要获取当前形状的运行时类型,则应使用the GetType method。从the typeof operator documentation
若要获取表达式的运行时类型,可以使用.NET Framework方法GetType,如下面的示例所示
这是你的情况。你既不需要typeof也不需要nameof。你甚至不需要泛型,因为你想要当前示例的运行时类型。

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.
}

您失败了,因为您使用过C++,它也是静态类型的,但有区别。正如您所知,在C++中,模板参数是在编译时替换的,而在.NET中,它们是在运行时替换的。我建议您阅读Differences Between C++ Templates and C# Generics

8qgya5xd

8qgya5xd4#

使用typeof(T)作为你的键,nameof,如果它有效的话,实际上将是一个可怕的选择,因为它返回的名称是不合格的,所以没有任何东西可以确保键是唯一的。

j7dteeu8

j7dteeu85#

使用typeof(T)。仅名称...不需要形状

相关问题