在强制T类型的情况下将泛型类型转换为“as T”

25

我觉得我可能漏掉了一些技巧,而且我从来没有做过这件事。然而,我应该如何使用 "as" 关键字转换通用类型?

[Serializable]
public abstract class SessionManager<T> where T : ISessionManager
{

    protected SessionManager() { }

    public static T GetInstance(HttpSessionState session)
    {

        // Ensure there is a session Id
        if (UniqueId == null)
        {
            UniqueId = Guid.NewGuid().ToString();
        }

        // Get the object from session
        T manager = session[UniqueId] as T;
        if (manager == null)
        {
            manager = Activator.CreateInstance<T>();
            session[UniqueId] = manager;
        }

        return manager;

    }

    protected static string UniqueId = null;

}

这行代码T manager = session[UniqueId] as T;会抛出以下错误:

类型参数 'T' 不能与 'as' 运算符一起使用,因为它既没有类类型约束,也没有'class'约束。

现在,我想我明白了原因;我没有直接告诉编译器T是一个类。如果我替换成:

public abstract class SessionManager<T> where T : ISessionManager

使用

public abstract class SessionManager<T> where T : class

......然后代码成功构建。

但我的问题是:如何在泛型类型上同时实施类和ISessionManager的强制要求?我希望有一个非常简单的答案。

编辑: 补充一下,我尝试过:where T : ISessionManager, class,结果我没有正确读取编译器错误。很简单,只需在ISessionManager之前放置class即可解决问题。我没有阅读的错误是:

"'class'或'struct'约束必须在任何其他约束之前出现。"

愚蠢的瞬间结束。


2
顺便提一句,在这里你不应该使用 CreateInstance<T>。你应该添加一个 new() 约束,并在代码中简单地使用 new T() - Mehrdad Afshari
从来不知道这个!谢谢。 - djdd87
3个回答

43
... where T : class, ISessionManager

如果您想在这里使用关键字,这里有一个示例,还使用了泛型。

    public void store<T>(T value, String key)
    {
        Session[key] = value;
    }

    public T retrieve<T>(String key) where T:class
    {
        return  Session[key] as T ;
    }

Ar**。我一直在写的是 where T : ISessionManager, class! - djdd87

15
where T : class, ISessionManager

你可以更进一步。
where T : class, ISessionManager, new()

这将会强制要求非抽象类且没有参数的构造函数被作为T传入。

4

阅读有关C#类型参数的限制的内容。

在这种特定情况下,您必须确保T是一个类:

public abstract class SessionManager<T>
    where T : class, ISessionManager

3
那样无法构建。;) 必须先定义类。此外,特定类型的所有限制必须在单个 where 子句中指定... - djdd87

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接