如何在C#中传递任意数量的参数

时间:2009-01-28 20:56:10

标签: c# arrays parameters

好的我需要设计一种方法来跟踪每个项目的存在量。 大约有26个项目。我还需要一种方法来确定是否存在特定的项目组合。

例如, 这是纸牌游戏的引擎。每张卡都有不同的类型,每张卡都可以附加卡。 需要将卡片附加到卡片上以便玩家在游戏中做某些事情。 为了简化这个程序,我想做一些像

这样的事情
if (meetsCrit(2, water, 4, ground))
{
    do this()
}
else
{
    displayerror()
}

编辑:已解决!

我使用了以下几篇文章中描述的技术组合。 特别提到:

Jon Skeet, Rinat Abdullin, 弗兰克,

无论如何,这就是我所做的 我创建了一个名为pair的类,它存储我正在寻找的类型,以及该类型的数量。 然后我使用Predicate Delegate查找所有类型并计算有多少, 然后我将它与我正在搜索的数字进行比较,并分别返回true或false。

这是它的代码

public bool meetsCrit(params Pair[] specs)
{
    foreach (Pair i in specs)
    {
        if (!(attached.FindAll(delegate(Card c) { return c.type == i.type; }).Count >= i.value))
        {
            return false;
        }

    }
    return true;
}

13 个答案:

答案 0 :(得分:23)

使用params

  

params 关键字允许您指定一个method parameter,它接受​​参数数量可变的参数。

     

方法声明中 params 关键字后不允许使用其他参数,方法声明中只允许使用一个 params 关键字...

答案 1 :(得分:14)

使用params关键字传递可变数量的参数:

   private static void HowMayItems<T>(params T[] values) {
        foreach (T val in values) { 
            //Query how many items here..
        }
    }

你也可以创建一个谓词并传递一个参数过滤器。在该方法中,您可以返回所有结果的并集。像这样的事情:

public class Item { 
    public string Name { get; set; }
}
public class ItemFilter {
    public string Name { get; set; }
    public ItemFilter(string name) {
        Name = name;
    }
    public bool FilterByName(Item i) {
        return i.Name.Equals(Name);
    }
}

public class ItemsTest {
    private static List<Item> HowMayItems(List<Item> l,params ItemFilter[] values)
    {
        List<Item> results= new List<Item>();
        foreach(ItemFilter f in values){
            Predicate<Item> p = new Predicate<Item>(f.FilterByName);
            List<Item> subList = l.FindAll(p);
            results.Concat(subList);
        }
        return results;
    }
}

编辑:

好的,我的混合坚果版本怎么样:):

public enum ItemTypes{
    Balloon,
    Cupcake,
    WaterMelon
    //Add the rest of the 26 items here...
}

public class ItemFilter {
    private ItemTypes Type { get; set; }
    public ItemFilter(ItemTypes type) {
        Type = type;
    }
    public bool FilterByType(ItemTypes type) {
        return this.Type == type;
    }
}

public class PicnicTable {
    private List<ItemTypes> Items;

    public PicnicTable() {
        Items = new List<ItemTypes>();
    }

    public void AddItem(ItemTypes item) {
        Items.Add(item);
    }

    public int HowMayItems(ItemTypes item)
    {
        ItemFilter filter = new ItemFilter(item);
        Predicate<ItemTypes> p = new Predicate<ItemTypes>(filter.FilterByType);
        List<ItemTypes> result = Items.FindAll(p);
        return result.Count;
    }
}

public class ItemsTest {
    public static void main(string[] args) {
        PicnicTable table = new PicnicTable();
        table.AddItem(ItemTypes.Balloon);
        table.AddItem(ItemTypes.Cupcake);
        table.AddItem(ItemTypes.Balloon);
        table.AddItem(ItemTypes.WaterMelon);
        Console.Out.WriteLine("How Many Cupcakes?: {0}", table.HowMayItems(ItemTypes.Cupcake));
    }
}

答案 2 :(得分:10)

params数组是明显的答案。另一种方法是创建一个表示标准的类。然后,您可以使用集合初始值设定项,例如:

bool result = myCollection.Contains(new Criteria {
                 { 2, Item.Balloon },
                 { 4, Item.Cupcake }
              });

但如果这也没用,我们肯定需要更多信息。

如果您可以提供一个示例,您喜欢调用该方法的语法,那肯定会对我们有所帮助。

答案 3 :(得分:3)

params关键字允许您以非数组形式传递任意数量的参数。但是,它们将被转换为函数内的数组。我不知道任何编程结构会与任何语言的编程结构不同。

答案 4 :(得分:1)

好的,因为我觉得这样,有些代码可以计算出你在一些列表中有多少个类型的实例...

我需要有趣的柜台:

  public class FunnyCounter
  {
    Dictionary<Type, int> restrictions = new Dictionary<Type, int>();
    public FunnyCounter Add<T>(int appears)
    {
      restrictions.Add(typeof(T), appears);
      return this;
    }

    public void PassThrough(object o)
    {
      if (restrictions.ContainsKey(o.GetType()))
        restrictions[o.GetType()] = restrictions[o.GetType()] - 1;
    }

    public bool SatisfiedAll()
    {
      return restrictions.Values.Aggregate(true, (b, i) => b && i == 0);
    }

现在有一个像

这样的列表
List<Stuff> l = new List<Stuff> { new Ball(), new Ball(), new Bucket() };

我做......

FunnyCounter counter = new FunnyCounter();
counter.Add<Ball>(2).Add<Bucket>(1);
l.ForEach(counter.PassThrough);
Console.WriteLine(counter.SatisfiedAll());

答案 5 :(得分:1)

以下是我将以简化方式完成此操作的方法:

var collection = new[] {Item.Baloon, Item.Cupcake, Item.Baloon, Item.Coke};

var result = collection.Contains(2.Baloons(), 1.Cupcakes());

其中:

public enum Item
{
    Baloon,
    Cupcake,
    Coke
}

public static class TableExtensions
{
    public static Pair<Item, int> Baloons(this int count)
    {
        return Tuple.From(Item.Baloon, count);
    }

    public static Pair<Item, int> Cupcakes(this int count)
    {
        return Tuple.From(Item.Cupcake, count);
    }

    public static bool Contains(this IEnumerable<Item> self, 
        params Pair<Item, int>[] criteria)
    {
        foreach (var pair in criteria)
        {
            var search = pair.Key;
            if (self.Count(item => item == search) < pair.Value)
                return false;
        }
        return true;
    }
}

说明:

  • 您不关心参数中项目的顺序。
  • 我使用枚举来表示对象,但这些也可以是对象
  • 元组来自Lokad.Shared
  • 包含当前搜索“至少X项”。通过传递可枚举的实际谓词 - 规则的条件对象,我们可以更具灵活性。这会保持语法相同,但允许有更多选项(例如: AtLeast AtMost ,X。 VegetarianSets ,Y。饮料等)。如果有兴趣,请查看validation and business rules application block中预定义的验证规则,了解类似的规则组合方法。

答案 6 :(得分:0)

除了使用params关键字,这将强制您在数组中添加项目,目前在C#中不支持此项。 C#4.0会在语言中引入可选参数,但我不确定它是否足够任意

答案 7 :(得分:0)

我会使用一个可以针对您的数据源进行评估的谓词,然后对其进行评估,从Predicate返回结果。

答案 8 :(得分:0)

这些物品是如何存放的?它们应存储在项集合对象中。它应该有必要的方法来检查它的内部。

或者使用实现IItem接口的params对象数组。

答案 9 :(得分:0)

bool doTheseItemsExist(List criteria) { .. }

你能不能简单地传入一个对象列表?从技术上讲,它类似于传递一个数组,但它很容易使用,如果你使用params,你不必加载可能是一个大型参数列表的调用堆栈。 (当然,最后一部分完全取决于您打算搜索的标准数量。)

(编辑:实际上,该列表需要是对象类型和预期数量的映射。)

但是那些建议你的收藏品应该在你的收藏中公开这些问题的绅士可能就是胜利者。一种可能性:

bool MyCollection.HasBalloons(int numBalloons);
bool MyCollection.HasCupcakes(int numCupcakes);
bool MyCollection.HasPartyHats(int numHats);

但是然后bool结果对调用者来说是模棱两可的......有这么多吗?至少有这么多?所以也许更好的方向是:

int MyCollection.NumBalloons();
int MyCollection.NumCupcakes();
int MyCollection.NumPartyHats();

然后,您不需要一些带有任意参数的额外函数。您可以根据需要简单地检查集合。

答案 10 :(得分:0)

数组可能会完成这项工作,但它并不完美。 你有一个类,其中包含一些具有不同类型项目的集合吗? 另一个更准确的解决方案是使用词典

Dictionary<String, int> numberOfEach = new Dictionary<string, int>();
numberOfEach.Add("balloons", 2);
numberOfEach.Add("cupcakes", 4);

然后你将在你的班级(带收藏的那个)中有一个方法

public bool correctAmmounts(Dictionary<String, int> numberOfEach)
{
    return collection1.Count == numberOfEach["balloons"] &&
           collection2.Count == numberOfEach["cupcakes"];
}

其中collection1有一些气球,而collection2有一些纸杯蛋糕。

但是,如果不同类型的数量发生变化,则必须编辑方法。

答案 11 :(得分:0)

我想知道问题是否有些破裂。 如果你问一些对象,如果它包含n和y中的n,则可以枚举你的对象。在这种情况下,它应该实现IEnumerable,其中T将是“你的内容的共同点”。 从这里你可以使用例如LINQ获取您的问题的答案或将这些问题封装在对象中并提供例如如Jon所示的标准系统......

答案 12 :(得分:0)

这听起来像是一个做OOP的好机会:

说你有一些代表你的物品的课程

public class Item
{
  public string Name{ get; set; }
  // Here put all the properties that are common to all items.
}

public class Cupcake : Item
{
  // By inheriting from Item, it will have Name 
  //  along with anything else you define there

  public bool HasFrosting{ get; set; }
  // Put whatever else Cupcake needs here
}

public class Baloon : Item
{
  public Color MyColor{ get; set; }
}

然后在您的应用程序代码中

// From your post, I can't tell where you're getting
//  your items, so I'll just put a placeholder here for now.
//  I assume this returns all kinds of items:
//  Cupcakes, Baloons, and other fun stuff
Item[] items = GetItemsFromSomewhere();

int cupcakeCount = GetCupcakeCount(items);

...

public int GetCupcakeCount( Item[] items )
{
  int cupcakeCount = 0;

  // This is the code for checking types of items
  //  you could use a LINQ statement or whatever you like
  //  but i just put a foreach loop here for simplicity
  foreach( Item item in items )
  {
    // Check the types of each object, 
    if(item is Cupcake)
     ++cupcakeCount;
  }

  return cupcakeCount;
}

即使您可以采用另一种方式,也可以考虑OOP,因为您似乎需要区分对象类型并进行比较。这可能是准确表示系统的好方法。