C# 强制将(泛型)值类型作为引用

C# 强制将(泛型)值类型作为引用,c#,reference,value-type,C#,Reference,Value Type,我有一个带有一些字段的结构。其中一个字段是泛型类型。泛型类型可以是引用类型或值类型 我想强制它在内部存储为引用,以避免结构变得太大 struct Foo<T> { T field; // should be a reference } 是的,当然,我可以自己写。但我试图避免将T定义为类 struct Foo<T> where T : class { T field; // Now it's a reference type. } struct Foo其中T:c

我有一个带有一些字段的结构。其中一个字段是泛型类型。泛型类型可以是引用类型或值类型

我想强制它在内部存储为引用,以避免结构变得太大

struct Foo<T>
{
  T field; // should be a reference
}

是的,当然,我可以自己写。但我试图避免将T定义为类

struct Foo<T> where T : class
{
  T field; // Now it's a reference type.
}
struct Foo其中T:class
{
T field;//现在它是引用类型。
}

如果您希望它成为一个实例:

where T : new()
可以使用
Tuple
保存值类型变量(
Tuple
是BCL中的类)

structfoo
{
元组字段;
}

如果您试图绝对确保任何值类型都已装箱,请将其存储在对象字段中,并使用属性强制执行通用约束;即:

struct Example<T>
{
    private object obj;
    public T Obj
    {
        get
        {
            return (T)obj;
        }
        set
        {
            this.obj = value;
        }
    }
}
struct示例
{
私有对象对象;
公共目标
{
得到
{
返回(T)obj;
}
设置
{
this.obj=值;
}
}
}

它将始终是一个实例或空引用。如果T类型的对象需要在运行时通过T类型的默认构造函数实例化,请使用new()。不,我不想强制T是一个类。当T是一个值类型时,我希望它存储为引用。您可以简单地将
字段
框入对象类型[这是我想到的唯一gud解决方案]。你到底想做什么?我不想结构变得太大。结构的内存使用量应该很小。此结构中还有其他字段,并且已处于上限。如果T是Guid或更大的值类型,则生成的结构将非常大。我不明白这是如何解决问题的。假设S是一个大值类型。那么Foo与S的大小相同。如果用户对S的性能很满意,那么为什么他们对Foo的性能不满意呢?装箱S—无论是使用对象装箱还是自定义装箱类装箱—总体上将使用更多的空间,因为必须为S实例留出空间,为箱子留出空间。装箱将占用更多的时间,因为装箱和取消装箱需要时间。如果存在大量的引用类型,则将S保持在引用类型中将给垃圾收集器增加相当大的压力。你能解释一下为什么你认为这是一种胜利吗?因为在我看来,这好像是在制造一个糟糕的局面——也就是说,一个大型结构的性能成本——要糟糕得多。@Eric:我不希望结构变得太大。结构的内存使用量应该很小。此结构中还有其他字段,并且已处于上限。如果T是一个Guid或更大的值类型,那么生成的结构将是big.OK,那么为什么Foo首先是一个结构?让Foo成为一门课。问题解决了。或者不是。你没有说问题出在哪里,所以除了猜测之外,你不可能做更多的事情。如果没有相应的成本,你不会得到任何收益;您可以牺牲更多的复制时间(通过使用结构)或更多的收集压力(通过使用类),但避免这两种情况的唯一方法是首先减少程序中的数据。您需要避免的成本是什么,复制成本还是收集成本?@Eric:我希望Foo是一个struct(出于各种原因,一个是避免null),T是一个引用,因为Foo的总大小。总是。即使T是一个值类型。称之为“显式装箱”。类型安全性很好(可接受的答案不是)。就这样。现在还不清楚吗?但是,应该注意的是,根据您使用此结构的方式,对于两个相同的值,结构的原始内存可能会有所不同,因为结构不是内部的,而长方体将具有不同的指针。Equals方法仍然适用于托管比较,因此这只是特定托管->本机转换的一个问题。我认为Tuple是一个值类型,但显然不是,所以我建议使用coop的答案。
struct Foo<T>
{
    Tuple<T> field;
}
struct Example<T>
{
    private object obj;
    public T Obj
    {
        get
        {
            return (T)obj;
        }
        set
        {
            this.obj = value;
        }
    }
}