C#泛型类使用引用类型和可为空的值类型 [英] C# generic class using reference types and nullable value types

查看:206
本文介绍了C#泛型类使用引用类型和可为空的值类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个有趣的问题。我想创建一个可以处理两种引用类型以及 Nullable< T> 类型的泛型类。基本上我想要这样的东西:

  public class ClassWithNull< T> 
{
public T varName = null;

$ / code>

现在这当然不会编译,因为并非所有类型都可以分配null,即不可为空的值类型。但问题是 Nullable< T> 是一个值类型,因此只需添加,其中T:class 不起作用我。我的generics-foo不是太强大,但我一直无法找到任何说 T 必须是引用类型或可为空值类型的方法。

我必须解决这个问题的想法是使一个抽象类成为 ClassWithNull< T> 。然后我可以添加两个子类,一个用于处理引用类型,另一个用于处理可为空的值类型。然后,基类中的静态工厂方法可以使用反射来确定应该构建哪个子类。例如:

  public static ClassWithNull< T> CreateClassWithNull< T>()
{
StackTrace st = new StackTrace();
Type type = st.GetFrame(1).GetMethod()。GetGenericArguments()[0];
if(!type.IsValueType)
{
return new ClassWithReferenceType< T>();
}
else if(type == typeof(Nullable))
{
return new ClassWithNullableValueType< T>();
}
else
{
抛出新的异常(必须提供可为空的类型。);


$ / code>

这里的问题是泛型是静态解析的。如果 ClassWithReferenceType< U> 期望 U 成为引用类型,则调用 new ClassWithReferenceType<工厂方法中的T>()是一个编译错误,因为 T 不需要是引用类型。编译器不知道运行时检查。



有关如何实现这种事情的任何想法?

解决方案

如何:

  public class ClassWithNull< T> 
{
public T varName = default(T);

$ / code>

(其实,你甚至不需要任务 - 你可以离开它是建设中的默认值,但你可能需要默认(T)作为局部变量。)



这不会阻止你错误地使用它的非空值类型 - 但是这足够吗?

如果这对你没有帮助,我会建议写 两个静态方法,如下所示:

  public static ClassWithNull< T> CreateClassWithNullForClass< T> T:class 
{
return new ClassWithReferenceType< T>();
}

public static ClassWithNull< T> CreateClassWithNullForNullable< T> T:struct
{
return new ClassWithNullableValueType< T>();

ClassWithNullableValueType 会是可为空< T> - T 是基础类型。



现在,如果您想要使用同一方法的重载,则会变得更加困难,特别是如果您不想传递任何参数。这是可能,但 真的很可怕


I have an interesting problem. I'd like to create a generic class that can deal with both Reference types as well as Nullable<T> types. Basically I want something like:

public class ClassWithNull<T>
{
    public T varName = null;
}

Now this, of course, does not compile because not all types can be assigned null, namely non-nullable value types. But the problem is Nullable<T> is a value type, so simply adding where T : class doesn't help me. My generics-foo is not too strong, but I haven't been able to find any way to say that T must either be a reference type or a nullable value type.

The idea I have to solve this is to make ClassWithNull<T> an abstract class. I could then add two sub-classes, one to deal with reference types and one to deal with nullable value types. Then, a static factory method in the base class could use reflection to determine which sub-class ought to be constructed. Something like:

public static ClassWithNull<T> CreateClassWithNull<T>()
{
    StackTrace st = new StackTrace();
    Type type = st.GetFrame(1).GetMethod().GetGenericArguments()[0];
    if (!type.IsValueType)
    {
        return new ClassWithReferenceType<T>();
    }
    else if (type == typeof(Nullable))
    {
        return new ClassWithNullableValueType<T>();
    }
    else
    {
        throw new Exception("Must provide nullable type.");
    }
}

The problem here is that generics are resolved statically. If ClassWithReferenceType<U> expects U to be a reference type, then calling new ClassWithReferenceType<T>() in the factory method is a compilation error since T is not required to be a reference type. The compiler does not know about the run time check.

Any ideas about how to implement such a thing?

解决方案

How about:

public class ClassWithNull<T>
{
    public T varName = default(T);
}

(Actually, you don't even need the assignment - you can just leave it to be the default value on construction. But you might want default(T) for local variables.)

That won't stop you from using it incorrectly with a non-nullable value type - but is that enough?

If that doesn't help you, I would suggest writing two static methods, like this:

public static ClassWithNull<T> CreateClassWithNullForClass<T> where T : class
{
    return new ClassWithReferenceType<T>();
}

public static ClassWithNull<T> CreateClassWithNullForNullable<T> where T : struct
{
    return new ClassWithNullableValueType<T>();
}

The field in ClassWithNullableValueType would be Nullable<T> - T would be the underlying type.

Now if you want overloads of the same method, that gets a little harder, particularly if you don't want to pass any parameters. It's possible, but really, really horrible.

这篇关于C#泛型类使用引用类型和可为空的值类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆