在运行时生成通用类型

发布于 2024-10-18 10:36:28 字数 736 浏览 1 评论 0原文

我想知道是否可以使用一个变量的类型设置为另一个泛型变量的类型?

例如,假设我有这个代码:

public class Foo: IBar<ushort>
{
    public FooBar()
    {
        Value = 0;
    }

    public ushort Value { get; private set; }
}

我也有这个类:

public class FooDTO<TType> : IBar<TType>
{
    public TType Value { get; private set; }
}

在这些示例中,在 IBar 的接口中具有属性

TType Value;

然后在我的代码中我有这个 这

var myFoo = new Foo();
var fooDataType = myFoo.Value.GetType();

//I know this line of code does not compile, but this is what I am looking to be able to do
var myFooDTO= new FooDTO<fooDataType>();

是我正在寻找的可能吗?对于高使用率的代码来说会不会太慢(因为使用了反射。

I am wondering if it is possible to use the type of one variable to set as the type of another generic variable?

For example, say I have this code:

public class Foo: IBar<ushort>
{
    public FooBar()
    {
        Value = 0;
    }

    public ushort Value { get; private set; }
}

I also have this class:

public class FooDTO<TType> : IBar<TType>
{
    public TType Value { get; private set; }
}

In these examples, in the interface for IBar has the property

TType Value;

Then in my code I have this

var myFoo = new Foo();
var fooDataType = myFoo.Value.GetType();

//I know this line of code does not compile, but this is what I am looking to be able to do
var myFooDTO= new FooDTO<fooDataType>();

Is what I am looking for possible? Would it be too slow for high use code (because of using reflection.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

土豪 2024-10-25 10:36:28

您可以通过反射,使用 Type.MakeGenericType

由于反射,这会产生一些开销,因此您需要对其进行分析,看看这对您来说是否会成为问题。

You can do this via Reflection, by using Type.MakeGenericType.

This will have some overhead due to reflection, so you'd need to profile it to see if that will be an issue for you.

知你几分 2024-10-25 10:36:28

为什么不使用方法类型推断:

public class FooDTO<TType> {
    public TType Value { get; private set; }
}

public class Foo : FooDTO<ushort> { }

static FooDTO<T> GetTypedFoo<T>(T Obj) {
    return new FooDTO<T>();
}

static void Main(string[] args) {
   Foo F = new Foo();

   var fooDTO = GetTypedFoo(F.Value);
}

Why not use Method type inference:

public class FooDTO<TType> {
    public TType Value { get; private set; }
}

public class Foo : FooDTO<ushort> { }

static FooDTO<T> GetTypedFoo<T>(T Obj) {
    return new FooDTO<T>();
}

static void Main(string[] args) {
   Foo F = new Foo();

   var fooDTO = GetTypedFoo(F.Value);
}
心碎无痕… 2024-10-25 10:36:28

总是当我在一个句子中读到“通用”和“运行时”时,我总是想到“糟糕的设计”或“不理解通用的含义”。可能两者皆有。

泛型参数是类型的组成部分。所以说“在运行时生成通用类型”与“在运行时生成 Foo 类”相同。您要么寻找反思,要么改变算法的设计。

在这种情况下, var 关键字也不会为您提供帮助。忘记它吧。

Always when I read "generic" and "runtime" in one sentence, I always thing "bad design" or "doesnt understant what generic means". Possibly both.

Generic parameter is integral part of the type. So saying "Generate Generic Type At Runtime" is same as "Generate Foo class at runtime". You are either looking for reflection or change design of your algorithm.

Also var keyword is not going to help you in this case. Forget about it.

总以为 2024-10-25 10:36:28

您正在寻找编译时反射,这是 C# 所没有的功能。因此,如果您正在寻求性能优化,那么解决方案比问题本身更糟糕。

D 确实有这个功能;您可以轻松地

int x = 0;
typeof(x) y = x + 2;

在 D 中编写甚至更复杂的表达式,并且所有这些都在编译时进行评估。

You're looking for compile-time reflection, a feature that C# doesn't have. So if you're looking for performance optimizations, the solutions are worse than the problem.

D does have this feature, though; you can easily write

int x = 0;
typeof(x) y = x + 2;

or even much more complicated expressions in D, and it's all evaluated at compile-time.

想挽留 2024-10-25 10:36:28

您想要的核心是:

var type = typeof(FooDTO<>).MakeGenericType(fooDataType);
object obj = Activator.CreateInstance(type);

但是,您会注意到这是反射,并且几乎将您与对象联系在一起。通常的解决方法是访问 API 的非通用版本,以便您可以使用 object - 例如(添加非通用 IBar< /code>):

IBar bar = (IBar)Activator.CreateInstance(type);

当然,您可以将运行时/泛型移至更高的位置 - 也许移至泛型方法中;那么泛型方法中的所有内容都可以使用 T,并且您可以使用 MakeGenericMethod 在仅在以下位置已知的特定 T 上下文中执行该方法运行时。

The core of what you want is:

var type = typeof(FooDTO<>).MakeGenericType(fooDataType);
object obj = Activator.CreateInstance(type);

however, you'll notice that this is reflection, and pretty much ties you to object. The usual workaround to this is to have access to a non-generic version of the API, so that you can work with object - for example (with the addition of a non-generic IBar):

IBar bar = (IBar)Activator.CreateInstance(type);

You can of course move the runtime/generics hit higher up - perhaps into a generic method; then everything in the generic method can use T, and you can use MakeGenericMethod to execute that method in the context of a particular T known only at runtime.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文