8

假设我有以下课程:

public class GenericClass<T>
{
    public T Find()
    {
        //return T if found otherwise null or Nullable<T>
    }
}

在某个地方,我想使用 a 来专门化我的课程Tclass其他时候使用 a struct。我正面临这个问题Nullable<T>:如果T类型不限于 a ,我无法返回a struct

我想提供一个我的Find方法的实现,如果T它专门用于 aclass或 a struct。如果Find失败,我想返回nullifT是一个类,否则Nullable<T>

不使用反射有可能吗?如果是怎么办?

4

3 回答 3

16

你可以退货default(T)

对于一个类,这将是null. 对于 any Nullable<T>,这将是一个Nullable<T>没有值的(有效地null)。

话虽如此,如果您将其与 astruct而不是 aNullable<T>作为类型一起使用,default(T)则将是结构的默认值。


如果您想让任何类或结构统一地工作,您可能需要返回两个值 - 您可以在这里使用框架作为灵感,并拥有一个 TryXXX 方法,即:

public bool TryFind(out T)

然后,您可以default(T)在未找到该值时使用,并返回 false。这避免了对可空类型的需要。Tuple<bool, T>如果您想避免使用 out 参数,您也可以编写此返回 a或类似内容,即:

public Tuple<bool, T> Find()

最后一个选项,可能是让你的类非泛型,然后使用一对泛型方法:

class YourClass // Non generic
{
    public T FindReference<T>() where T : class
    {
         // ...
        return null;
    }

    public Nullable<T> FindValue<T>() where T : struct
    {
         // ...
         return default(T);
    }
}

请注意,您需要不同的名称,因为您不能拥有纯粹基于返回类型的重载方法。

于 2012-10-30T16:29:49.033 回答
2

我会使用以下解决方案:

public Boolean Find(out T result)
{
    // Pseudo code
    if (FindItem == true)
    {
        result = ItemFound;
        return true;
    }
    result = default(T);
    return false;
}

为什么?因为Nullable<T>只接受一个结构并且上面的方法同时支持类和结构。

于 2012-10-30T16:31:15.157 回答
0

正如里德所说,你可以回来default(T)

在我看来,这有一个很大的缺点:如果您的方法声明default(T)如果未找到该项目则返回,那么您将失去返回值类型的默认值的能力(例如,返回0forFind<int>通常可能是一个完全有效的返回值)。

我宁愿去做这样的事情

public class GenericClass<T>
{
    public Option<T> Find()
    {
        //return Option.Some(item) if found otherwise Option.None<T>()
    }
}

public static class Option
{
    public static Option<T> None<T>()
    {
        return new Option<T>(default(T), false);
    }

    public static Option<T> Some<T>(T value)
    {
        return new Option<T>(value, true);
    }
}

public sealed class Option<T>
{
    private readonly T m_Value;
    private readonly bool m_HasValue;

    public void Option(T value, bool hasValue)
    {
        m_Value = value;
        m_HasValue = hasValue;
    }

    public bool HasValue 
    {
        get { return m_HasValue; }
    }        

    public T Value 
    {
        get { return m_Value; }
    }
}
于 2012-10-30T16:45:08.730 回答