在接口中使用泛型

时间:2009-06-01 23:07:05

标签: c# generics collections interface

如何在以下代码中允许CookieData通用?我在ICookieService2的声明中遇到编译时错误。

public struct CookieData<T>
{
    T Value { get; set; }
    DateTime Expires { get; set; }
}

public interface ICookieService2: IDictionary<string, CookieData<T>>
{
   // ...
}

我的错误是:

  

找不到类型或命名空间名称'T'(您是否缺少using指令或程序集引用?)

我希望ICookieService2将通用数据插入其中。谢谢!

修改这不会将我锁定为单个T以构建任何ICookieService2吗?

编辑2 我要做的是以下内容:

CookieData<int> intCookie = { Value = 27, Expires = DateTime.Now };
CookieData<string> stringCookie = { Value = "Bob", Expires = DateTime.Now };

CookieService2 cs = new CookieService2();
cs.Add(intCookie);
cs.Add(stringCookie);

8 个答案:

答案 0 :(得分:7)

看起来你有3个选项

使ICookieService2通用

public interface ICookieService2<T> : IDictionary<string, CookieData<T> {
...
}

为CookieData创建一个非泛型基类,并在接口

中使用它
public interface ICookieData {}
public class CookieData<T>: ICookieData{}
public interface ICookieService2 : IDictionary<string, ICookieData> {}

选择具体实施

public interface ICookieService : IDictionary<string, CookieData<int>> {}

答案 1 :(得分:4)

你也必须使ICookieService2成为通用的:

public interface ICookieService2<T>: IDictionary<string, CookieData<T>>
{
   // ...
}

答案 2 :(得分:2)

好的,这就是你想要的:

public interface ICookieDataBase
{
    DateTime Expires { get; set; }
}

public struct CookieData<T> : ICookieDataBase
{
    public T Value { get; set; }
    public DateTime Expires { get; set; }
}

public class ICookieService : IDictionary<string, ICookieDataBase>
{
    // ...
}

public void DoWork()
{
    var intCookie =
        new CookieData<int> { Value = 27, Expires = DateTime.Now };

    var stringCookie =
        new CookieData<string> { Value = "Bob", Expires = DateTime.Now };

    ICookieService cs = GetICookieService();
    cs.Add(intCookie);
    cs.Add(stringCookie);
}

答案 3 :(得分:1)

我认为你想要的是:

public interface ICookieService2<T>: IDictionary<string, CookieData<T>>
{
   // ...
}

目前ICookieService2不是通用的,因此未定义T.

这允许您创建工具ICookieService2<string>ICookieService2<int>等的类

编辑: 回应您的最新要求,我认为这实际上取决于您需要什么。但是,这样的事情对你有用。

public interface ICookieData
{
    object Value {get;} // if you need to be able to set from CookieService, life gets harder, but still doable.
    DateTime Expires {get;}
}

public struct CookieDate<T> : ICookieData
{
    T Value {get;set;}
    DateTime Expires {get;set;}

    object ICookieData.Value
    {
        get
        {
            return Value;
        }
    }
}

然后,CookieService可以是或具有List,您可以添加CookieData和CookieData。如果你需要从CookieService编写(设置),它会更复杂一些,并且最好不要使用泛型。但是,如果您只需要能够检索CookieData,那么这可能对您有用。

答案 4 :(得分:1)

您需要一个非通用接口来执行此操作:

public interface ICookieData
{
  // you need this to get the value without knowing it's type
  object UntypedValue { get; }
  // whatever you need additionally ...
  Type DataType { get; } 

  DateTime Expires { get; set; }
}

public struct CookieData<T> : ICookieData
{
    // ICookieData implementation
    public object UntypedValue { get { return Value; } }
    public Type DataType { get { return typeof(T); } }
    public DateTime Expires { get; set; }

    // generic implementation
    T Value { get; set; }
}

public interface ICookieService2: IDictionary<string, ICookieData>
{
   // ...
}

CookieData<int> intCookie = { Value = 27, Expires = DateTime.Now };
CookieData<string> stringCookie = { Value = "Bob", Expires = DateTime.Now };

CookieService2 cs = new CookieService2();
cs.Add(intCookie);
cs.Add(stringCookie);

答案 5 :(得分:0)

不确定C#,但Java的方式是声明你的ICookieService2拥有<T>参数,或者将<T>指定为CookieData中具体的内容}。

答案 6 :(得分:0)

如果我正确地理解了你的问题,你想要将泛型类型视为相同,但在当前的.NET实现中,你不能这样做。

CookieData&LT;串GT;不能作为CookieData&lt; int&gt;传递它们实际上是不同的类型,泛型类型不相关,不能像它们一样被转换或传递。创建ICookieService2作为开放的通用(意思是ICookieService2&lt; T&gt;)并不能解决问题,因为那时你会为每个不同的类型使用不同的ICookieService2类型,并且所有类型都将在不同的字典中。

您可以创建ICookieData接口并在CookieData&lt; T&gt;中实现它。并使用ICookieData将项目存储在字典中(正如Stefan已经建议的那样)。

您可以在C#4.0中执行您想要的操作(但有一些限制)。在那之前有一篇关于它的文章here,你必须将它作为非泛型类型传递给它们,例如接口,或者只是将value参数作为字典中的对象,因为你要去如果你使用原语作为类型参数,那么无论如何都要使用它。

答案 7 :(得分:0)

你可以尝试

public struct CookieData<T>
    where T : Object
{
    T Value { get; set; }
    DateTime Expires { get; set; }
}

这样,T的所有实例都将被强制使用基类型的Object。 (几乎C#中的所有内容(例如int == System.Integer等)。