泛型中 T 是实现接口的类

24

我有一个接口:

interface IProfile { ... }

...以及一个类:

[Serializable]
class Profile : IProfile 
{ 
  private Profile()
  { ... } //private to ensure only xmlserializer creates instances
}

...以及一位有方法的管理者:

class ProfileManager
{
  public T Load<T>(string profileName) where T : class, IProfile
  {
    using(var stream = new .......)
    {
      var ser = new XmlSerializer(typeof(T));
      return (T)ser.Deserialize(stream);
    }
  }
}

我希望这个方法可以像这样使用:

var profile = myManager.Load<Profile>("TestProfile"); // class implementing IProfile as T

...并在此处抛出编译时错误:

var profile = myManager.Load<IProfile>("TestProfile"); // NO! IProfile interface entered!

然而,所有内容都已编译,并且只有XmlSerializer抛出运行时错误。

我以为where T : class会确保仅接受类类型?

是否可以使编译器在输入IProfile(或其他继承自IProfile的接口)时抛出错误,并且仅接受实现IProfile的类类型?


XmlSerializer 会抛出什么错误? - default
1
@Default并不重要。问题在于,即使有“class”约束,T也可能是一个接口。 - user247702
@Default: InvalidOperationException{"IProfile 无法序列化,因为它没有无参构造函数"} - Anders
2个回答

41
根据MSDN中的类,T必须是引用类型;这也适用于任何类、接口、委托或数组类型。
一个解决方法是要求T实现无参构造函数,如下所示:
where T : class, IProfile, new()

3
我想过那个方法,但是 C# 要求构造函数必须是公共的。 :( - Anders
@Nautious 另外一种可能的方法是使用代码合同。 - Bob Vale
也许另一种可能性是创建一个抽象基类,并将约束设置为基类,而不是接口? - user247702
2
那样做行不通,因为Load<AbstractBase>(...)仍会编译通过并在运行时抛出异常。使用new()是解决这个问题的最佳方法。 - zmbq
@zmbq 是的,我没有认真考虑。 - user247702
@BobVale - 我正在使用 .Net 3.5 CF,所以合同不可用。我想我必须咬紧牙关,使用 'new()'。 - Anders

0

对我来说可行

public interface IUser
{
    int AthleteId { get; set; }
    string GivenName { get; set; }
    string FamilyName { get; set; }         
    bool IsActive { get; set; }
}

public  class DjsNameAutoSearch<Result, User> : where User : class, IUser, new()

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