我什么时候应该使用params Object []与Dictionary <string,object =“”>?</string,>

时间:2012-07-06 23:55:35

标签: c# .net params

我将API定义为接口,我们称之为IFoo,我想定义一个方法Bar()

此方法Bar()将获取一个必需参数,然后是一些任意数量的其他参数。对这些其他论点的解释将取决于IFoo

的实现者

对于这种情况,使用params或使用Dictionary<String, Object>来定义我的界面更合适。

public interface IFoo
{
   bool Bar(String id, params Object[] params);
}

或者

public interface IFoo
{
   bool Bar(String id, Dictionary<String, Object> params);
}

用户似乎更容易调用前者,但后者在其意图中更明确,因为对于前者,您必须按照特定顺序指定参数,以便实现正确解释它们你基本上是在做命名参数。

所以问题:

  • 我应该使用哪种形式(以及为什么?) - 这些被认为是最佳做法之一吗?
  • 我应该注意一种风格与另一种风格的特定优势吗?其中一个被认为是代码味道吗?
  • 是否有另一种模式可以以不同/更好的方式实现相同的目标?

为了记录,我知道.Net 4.0中的named parameters但是这个代码需要在.Net 3.5上编译,所以不能使用任何.Net 4.0+功能

修改

只是为了添加更多有关我的IFooBar()方法实际代表的内容的详细信息,因为有人问过。

IFoo代表一些存储子系统,Bar()实际上是一个创建操作。根据存储子系统Bar()可能不需要ID以外的任何参数,或者它可能需要许多参数。

编辑2

所以回应@Kirk Woll的评论和@ Fernando的回答这里有更多的信息。

我可能永远不会自己调用IFoo.Bar(),这个界面是开源框架的一部分。第三方开发人员将实现IFoo,最终用户将调用它的特定实例,让IFoo根本就是让用户更容易在存储子系统之间迁移他们的应用程序,因为他们可以代码到接口而不是特定的实现尽可能的人。

在最简单的情况下,底层存储子系统只有一种形式的存储,因此除了ID之外不需要任何参数。在复杂的情况下,存储子系统可以允许多种类型的存储,并且每种类型的存储可以允许任意复杂的一组配置参数,例如,索引大小,持久性,事务行为,索引策略,安全性和ACL考虑因素等。

我同意@Fernando可能更多的多态性可能有意义,也许多态性与泛型和类型限制相结合可能是最好的。例如。

public interface IFoo
{
  bool Bar<T>(T parameters) where T : IBarConfig;
}

public interface IBarConfig
{
  String ID { get; set; }
}

然后使用类似的实现:

public class MyFoo
{
  bool Bar<T>(T config) where T : MyBarConfig
  {
    //Implementation
  }
}

public class MyBarConfig : IBarConfig
{
  public String ID { get; set; }

  public long IndexSegmentSize { get; set; }

  //Etc...
}

这不是我的头脑,所以不确定在Bar()中定义MyFoo与其实现的接口有不同的类型限制是否合法?

5 个答案:

答案 0 :(得分:4)

您需要决定是否需要搜索或能够从params集合/数组中检索对象。

使用Object[] params时,对象上没有索引。您需要迭代整个集合以查找项目(通过其键)。

使用Dictionary<String, Object>时,您的对象会被其键标记,并且按键始终可以轻松搜索/查询。

根据您的需要,您需要决定您的方法。

字典搜索速度更快,但创建索引会产生开销。

答案 1 :(得分:2)

如果你需要内联编写它们,那么与Dictionary相比,

params提供更容易编写/读取代码。即每次调用String.Format时,映像构造字典 - 代码将是不可读的。另一方面,如果你已经有参数字典 - 可以使用它。

我建议您重新考虑API,看看您是否可以接受IEnumerable,甚至更好IEnumerable<T>作为参数。不幸的是,对于这样的通用IFoo样本名称,不可能看出这种方法是否有效。

答案 2 :(得分:1)

词典方法还有另一个问题:拼写错误。你可能需要定义很多常量来作为关键来避免这个问题。

为什么不选择多态解?

public interface IFoo {
    void Bar(FooData data);
}

public abstract class FooData {
     public int Id {get;set;}
}

public class MyFooData1 : FooData {
    public string SomeProperty {get;set;} 
    //...
}

public class MyFoo : IFoo {
    public void Bar(FooData data) {
        var myData = (MyFooData1)data;
        //...
    }
}

public class MyFooData2 : FooData {
    public int SomeOtherProperty {get;set;}
    //...
}

public class MyFoo2 : IFoo {
    public void Bar(FooData data) {
        var myData = (MyFooData2)data;
        //...
    }
}

你最终会得到更多更小的课程,但它们很容易测试和扩展。

<强>更新

@RobV如果你正在实现一个接口,你不能改变类型限制,但是,如果你将你的type参数放在接口声明中,你可以完成你想要做的事情:

public interface IFoo<T> where T : IBarConfig {
    void Bar(T parameters);
}

public class MyBarConfig: IBarConfig {
    public String ID { get; set; }
    public long IndexSegmentSize { get; set; } 
}

public class MyFoo : IFoo<MyBarConfig> {
  public void Bar(MyBarConfig config) {
    //Implementation
  }
}

答案 3 :(得分:0)

我应该使用哪种形式(以及为什么?) - 这些被认为是最佳实践之一吗? ---&GT;你应该使用第二个,因为它比第二个更容易出错。

关于替代模式,肯定有一种方法可以更好地实现这一点。你能告诉我们你的问题究竟是什么吗?而不是使用IFoo和Bar?除非我确切地知道你要做什么,为什么......

,否则我无法提出任何建议

答案 4 :(得分:0)

你提到可选参数这一事实让我觉得IDictionary<string,object>方法会更好 - 这是你在.Net 3.5中提供这种界面的最佳方法。你可以只是询问对象并做一些类似于MVC为htmlAttributes所做的事情(使用反射将匿名对象转换为IDictionary<string,object>)。

我更喜欢params object[]方法的情况是那些试图在每种情况下给它们起名字的情况只是奇怪/不可能,比如string.format