构造函数或显式转换

4
在使用Linq to Sql时,我创建了一个单独的类来传递数据到网页。为了简化创建这些传递对象,我要么使用专用构造函数,要么使用显式转换运算符。我的两个问题是:
第一,从可读性的角度来看,哪种方法更好?
第二,虽然对我而言生成的clr代码似乎相同,但是否存在一种情况,其中一个会被编译器(在lambda等情况下)处理得与另一个不同。
示例代码(DatabaseFoo使用专用构造函数,BusinessFoo使用显式运算符):
public class DatabaseFoo
{
    private static int idCounter; // just to help with generating data
    public int Id { get; set; }
    public string Name { get; set; }

    public DatabaseFoo()
    {
        Id = idCounter++;
        Name = string.Format("Test{0}", Id);
    }
    public DatabaseFoo(BusinessFoo foo)
    {
        this.Id = foo.Id;
        this.Name = foo.Name;
    }
}

public class BusinessFoo
{
    public int Id { get; set; }
    public string Name { get; set; }

    public static explicit operator BusinessFoo(DatabaseFoo foo)
    {
        return FromDatabaseFoo(foo);
    }


    public static BusinessFoo FromDatabaseFoo(DatabaseFoo foo)
    {
        return new BusinessFoo {Id = foo.Id, Name = foo.Name};
    }
}

public class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Creating the initial list of DatabaseFoo");
        IEnumerable<DatabaseFoo> dafoos = new List<DatabaseFoo>() { new DatabaseFoo(), new DatabaseFoo(), new DatabaseFoo(), new DatabaseFoo(), new DatabaseFoo(), new DatabaseFoo()};

        foreach(DatabaseFoo dafoo in dafoos)
            Console.WriteLine(string.Format("{0}\t{1}", dafoo.Id, dafoo.Name));

        Console.WriteLine("Casting the list of DatabaseFoo to a list of BusinessFoo");
        IEnumerable<BusinessFoo> bufoos = from x in dafoos
                                          select (BusinessFoo) x;

        foreach (BusinessFoo bufoo in bufoos)
            Console.WriteLine(string.Format("{0}\t{1}", bufoo.Id, bufoo.Name));

        Console.WriteLine("Creating a new list of DatabaseFoo by calling the constructor taking BusinessFoo");
        IEnumerable<DatabaseFoo> fufoos = from x in bufoos
                                         select new DatabaseFoo(x);

        foreach(DatabaseFoo fufoo in fufoos)
            Console.WriteLine(string.Format("{0}\t{1}", fufoo.Id, fufoo.Name));
    }
}
2个回答

6
我并不是完全喜欢转换 - 无论是显式的还是隐式的。相同的语法: (TypeName) expression 用于各种不同类型的转换,很容易混淆编译器应用哪种类型。
FromDatabaseFoo 这样的静态工厂方法很好 - 你可能还想在 DatabaseFoo 上有一个实例方法 ToBusinessFoo。在我看来,这两个比自定义转换更清晰。
(这并不意味着自定义转换总是不好的,只是我一般会谨慎使用它们。)

我可能会在DatabaseFoo类中使用静态的ToBusinessFoo和FromBusinessFoo,而避免将它们放在BusinessFoo中,因为重点是最小化BusinessFoo对数据的了解。我也不太喜欢转换。那么你更喜欢使用静态方法还是像这样使用构造函数:DatabaseFoo(businessFoo)? - Felan
2
@Felan:你可以将它作为DatabaseFoo的扩展方法来实现,这样DatabaseFoo本身就不知道它的存在,但看起来它确实存在。构造函数或静态方法对我来说并不重要,老实说。静态方法有一些优点,比如能够缓存或返回null,并且具有用于消除参数歧义的名称。构造函数更加典型。 - Jon Skeet

2
我建议你看一下AutoMapper。它可以使你的代码更加清晰,将对象之间的映射分离,使其独立且更具可重用性。

2
谢谢提供链接,非常有趣,我一定会尝试使用AutoMapper。在许多情况下,这样做会很方便。有时添加像AutoMapper这样的抽象似乎是为了避免穿过繁忙街道而走了一英里路。如果你只需要穿过一条繁忙的街道,那么额外的一英里路似乎不值得,但如果你必须穿过几条恶劣的街道,那么更长(最终会更短)和更干净的路径就会得到回报。 - Felan

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