如何在C#界面中返回Type T?

时间:2012-04-09 18:54:34

标签: c# generics c#-4.0 interface

我有这样的界面:

public interface IUser{
    //some properties here

    T ToDerived(User u);
}

我是接口开发的新手,所以这就是我想要完成的。我将有一个基类

public class User 

不实现上述接口。然后我将有一个派生类

SalesUser : User, IUser
{
    //no properties needed because they exist in the User class

    SalesUser ToDerived(User u)
    {
        //code for converting a base User to a derived SalesUser
    }
}

我想在SalesUser类中编写ToDerived(User u)的函数,但在界面中,我不知道如何定义这个,因为我现在在界面中的ToDerived方法声明没有编译。

我希望这是有道理的。

3 个答案:

答案 0 :(得分:14)

public interface IUser<T> where T : User
{
    //some properties here

    T ToDerived(User u);
}

SalesUser : User, IUser<SalesUser>
{
    //no properties needed because they exist in the User class

    SalesUser ToDerived(User u)
    {
        //code for converting a base User to a derived SalesUser
    }
}

不确定这是你想要的,但我在接口上添加了泛型类型约束,以确保泛型类型为User或从中继承。

答案 1 :(得分:3)

Oded的答案解决了编译问题,允许您定义满足接口的ToDerived方法。但是,正如我在评论中所说,我并不确定这是最好的实施方式。

我遇到的主要问题是,在静态上下文中通常需要这样的转换方法。您没有SalesUser的实例;你想要一个,并有一个用户,所以你在静态上下文(SalesUser.ToDerived(myUser))中调用该方法,你得到一个SalesUser(该方法将更恰当地命名为FromUser()或类似)。您在界面中指定的方法要求您已拥有SalesUser以将用户转换为SalesUser。我能想到的唯一一个你需要预先存在的SalesUser的情况是“部分克隆”;您正在使用来自传入的用户和您正在调用该方法的SalesUser的信息创建一个新的SalesUser实例。在所有其他情况下,您要么不需要SalesUser(转换,如上所述应该是静态的),或者您不需要用户(“克隆”或“深层复制”方法生成新实例与您调用方法的实例相同的数据。)

此外,您班级的消费者必须知道他们必须调用ToDerived()才能执行从用户到SalesUser的转换。通常,C#程序员会期望显式或隐式转换可用:

public class SalesUser
{

    public static explicit operator (User user)
    {
        //perform conversion of User to SalesUser
    }

}

//the above operator permits the following:
mySalesUser = (SalesUser)myUser;

...或者,如果转换运算符失败,可以使用用户构建SalesUser:

public class SalesUser:IUser
{
   public SalesUser(User user)
   {
      //initialize this instance using the User object
   }
}

//the above allows you to do this:
mySalesUser = new SalesUser(myUser);

//and it also allows the definition of a method like this,
//which requires the generic to be an IUser and also requires a constructor with a User
public void DoSomethingWithIUser<T>(User myUser) where T:IUser, new(User)
{ 
    //...which would allow you to perform the "conversion" by creating a T:
    var myT = new T(myUser);
}

现在,静态成员不满足接口定义,接口无法定义静态成员或构造函数签名。这告诉我IUser接口不应该尝试定义转换方法;相反,需要某种IUser的方法可以简单地指定,并且用户可以根据需要提供实现,而不需要知道它可以转换为自身。

答案 2 :(得分:0)

记住一个接口定义了一个类及其成员而没有提供任何实现,你可以创建一个接口,但接口必须有实现类。