簡體   English   中英

如何在C#中傳遞任意數量的參數

[英]How to pass an arbitrary number of parameters in C#

好的,我需要設計一種方法來跟蹤每個項目存在的數量。 大約有 26 個項目。 我還需要一種方法來確定是否存在某種項目組合。

例如,這是紙牌游戲的引擎。 每張卡都有不同的類型,每張卡都可以附加卡。 需要有一定的卡片組合附加到一張卡片上,以便玩家在游戲中做某些事情。 為了簡化這個程序,我想做一些類似的事情

if (meetsCrit(2, water, 4, ground))
{
    do this()
}
else
{
    displayerror()
}

編輯:解決了!

我使用了下面幾篇文章中描述的技術組合。 特別提醒:

喬恩·斯基特、里納特·阿卜杜林、弗蘭克、

無論如何,這就是我所做的,我創建了一個名為 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;
}

使用參數

params關鍵字允許您指定一個方法參數,該參數接受一個參數,其中參數的數量是可變的。

方法聲明中的params關鍵字后不允許附加參數,方法聲明中只允許一個params關鍵字...

使用 params 關鍵字傳遞可變數量的參數:

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

您也可以創建一個 Predicate 並將其傳遞給 params 過濾器。 在該方法中,您可以返回所有結果的並集。 像這樣的東西:

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));
    }
}

params 數組是顯而易見的答案。 另一種方法是創建一個類來表示標准。 然后您可以使用集合初始值設定項,例如:

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

但是,如果這也沒有用,我們肯定需要在問題中提供更多信息。

如果你能提供一個例子,你調用的方法的語法,這肯定會幫助我們。

params 關鍵字允許您以非數組形式傳遞任意數量的參數。 但是,它們將在函數內部轉換為數組。 我不知道任何編程結構會與任何語言中的結構有所不同。

好的,因為我喜歡它,一些代碼來計算你在某個列表中有多少個任意數量的類型的實例......

我需要有趣的計數器:

  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());

以下是我將如何以簡化的方式完成此操作:

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 項”。 通過傳遞實際上是可枚舉規則謂詞的標准對象,我們可以獲得更大的靈活性 這將保持語法相同,但允許有更多選項(即: AtLeastAtMost 、 X. VegetarianSets 、 Y. Drinks等)。 如果有興趣,請查看驗證和業務規則應用程序塊中預定義的驗證規則,以獲取類似的規則組合方法。

除了使用 params 關鍵字(這會強制您將項目添加到數組中)之外,目前 C# 中不支持此功能。 C# 4.0 將在語言中引入可選參數,但我不確定這對您來說是否足夠隨意

我會采用一個 Predicate ,它可以針對您的數據源進行評估,然后對其進行評估,從 Predicate 返回結果。

這些物品是如何儲存的? 它們應該存儲在一個項目集合對象中。 它應該有必要的方法來檢查它的內臟。

或者使用一個 params 對象數組來實現您的 IItem 接口。

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();

然后,您不需要一些帶有任意參數集的額外功能。 您可以根據需要簡單地檢查集合。

數組可能會完成這項工作,但它並不完全優雅。 你有一個包含不同類型項目的集合的類嗎? 另一個更精確的解決方案是使用字典

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 有一些紙杯蛋糕。

但是,如果不同類型的數量發生變化,您將不得不編輯您的方法。

我想知道這個問題是否有些破碎。 如果您詢問某個對象是否包含 n 個 this 和 y 個那個,則可以枚舉您的對象。 在這種情況下,它應該實現 IEnumerable ,其中 T 將是“內容的公分母”。 從這里開始,您可以使用例如 LINQ 來獲取您的問題的答案或將此類問題封裝在對象中,並提供例如 Jon 所展示的標准系統......

這聽起來像是做一些 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,因為您似乎需要區分對象類型並進行比較。 這可能是准確表示您的系統的好方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM