Передача типа как параметр шаблонной функции

Описание

Я хочу передать в параметр функции класс определенного типа и ожидать что в качестве результата выйдет экземпляр этого класса.
На TypeScript это выглядело бы так:

class Node {
    evaluate<T extends typeof Node>(type: T): InstanceType<T> {
        throw new Error(`Unable to evaluate ${type} from ${this}`);
    }
}

А на C# я не могу это реализовать. Онлайн конвертеры и учебники в интернете советуют делать так:

class Node
{
    public T Evaluate<T>(T type) where T : Node, new()
    {
        throw new Exception($"Unable to evaluate {type.Name} from {this.Name}");
    }
}

Но в таком случае компилятор не считает type типом и не находит type.Name:

'T' does not contain a definition for 'Name' and no accessible extension method 'Name' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?)

Вопрос

Как я могу реализовать описанную функцию на C#?

Дополнительно

Моей полной целью является создание абстрактного класса при наследовании которой можно было переопределить этот метод чтобы при его использовании можно было конвертировать экземпляр на тип другого потомка от Node.
Если объяснить по-человечески, то:

abstract class Node()
{
    public virtual T Evaluate<T>(T type) where T : Node, new()
    {
        throw new Exception($"Unable to evaluate {type.Name} from {this.GetType().Name}");
    }
}
class ValueNode(double value) : Node()
{
    public readonly double Value = value;
    public override T Evaluate<T>(T type)
    {
        if (type != ValueNode) throw new Exception($"Unable to evaluate {type.Name} from {this.GetType().Name}");
        return this;
    }
}
class IdentifierNode(string name) : Node()
{
    private static readonly Dictionary<string, double> Memory = new();
    public readonly string Name = name;
    public override T Evaluate<T>(T type)
    {
        if (type != ValueNode) throw new Exception($"Unable to evaluate {type.Name} from {this.GetType().Name}");
        if (!Memory.TryGetValue(this.Name, out double? value)) throw new Exception($"Identifier '{this.Name}' does not exist");
        return new ValueNode(value);
    }
}

class Program
{
    static void Main(string[] args)
    {
        { // Example 1
            ValueNode value = new(3.5);
            ValueNode result = value.Evaluate(ValueNode);
        }
        { // Example 2
            IdentifierNode identifier = new("Name");
            ValueNode result = identifier.Evaluate(ValueNode);
        }
    }
}

Если у вас есть лучшие варианты того, чего я пытаюсь сделать, то с удовольствием послушаю.


Ответы (1 шт):

Автор решения: Qwertiy

В ts типы - только при компиляции, поэтому надо что-то передавать в параметрах. А в C# типизация полноценная, поэтому аргументы этому методу вообще не нужны.

tio.run

using System;

class Node
{
  public string Name { get; set; }

  public T Evaluate<T>() where T : Node, new()
  {
    throw new Exception($"Unable to evaluate {typeof(T).Name} from {this.Name}");
  }
}

class Program
{
  public static void Main()
  {
    new Node() { Name = "Qwe" }.Evaluate<Node>();
  }
}
→ Ссылка