C# 有没有比使用字典作为参数更有效的方法

C# 有没有比使用字典作为参数更有效的方法,c#,C#,有没有更有效的方法 职能: public void someFunction(Dictionary<string, object> args){ foreach (var item in args){ Console.WriteLine("key: " + item.Key + " value: " + item.Value); } } 我想实现这样的功能,在这里我可以随时更改传递的变量名和值 someFunction(["number" => 3,

有没有更有效的方法

职能:

public void someFunction(Dictionary<string, object> args){
   foreach (var item in args){
       Console.WriteLine("key: " + item.Key + " value: " + item.Value);
   }
}
我想实现这样的功能,在这里我可以随时更改传递的变量名和值

someFunction(["number" => 3, "text" => "Some Text"]);
我想向函数传递一个字符串名和一个对象类型数组,这样我就可以遍历它了。这个代码可以工作,但我希望它看起来更整洁

在PHP中有

这使得变量名和数组中的值可以在代码中使用。用c#我得用一整本字典

我希望看到一种更有效的方法

编辑: 谢谢大家。不知道我会这么快得到答案0_0

当然,你可以使用关键字来允许动态数量的参数

例如,您可以这样做(它不必是a,它可以是a)

或者您可以使用更匿名的ValueTuple

public void AddSomeKeys(params (string, object)[] arguments) {
    foreach (var item in arguments){
        Console.WriteLine($"key: {item.Item1} value: {item.Item2}");
    }
}
在这两种情况下,您都可以调用如下方法:

AddSomeKeys(new KeyValuePair<string, object>( "item1", "value1" ), new KeyValuePair<string, object>( "item2", "value2" ) );
或与第三个版本

AddSomeKeys( ( "item1", "value1" ), ( "item2", "value2" ) );

如果只是为调用方寻找稀疏语法,可以使用匿名类型,类似于jquery传递可选选项的方式。例如:

public static void someFunction(object input)
{
    foreach (var p in input.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
             Console.WriteLine("{0}={1}", p.Name, p.GetValue(input));
}
函数本身有点混乱,但对于调用方来说,语法非常轻量级:

someFunction( new { Number = 3, Text = "Some text"});
输出:

Number=3
Text=Some text
如果你计划经常这样做,你可以用一种扩展方法来减轻一点痛苦。我把我的名字命名为
Extract()
,如下所示:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;

public static class ExtensionMethods
{
    public static Dictionary<string, object> Extract<T>(this T input) where T : class
    {
        return input
            .GetType()
            .GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .ToDictionary( p => p.Name, p => p.GetValue(input));
    }
}

public class Program
{
    public static void someFunction(object input)
    {
        var parameters = input.Extract();  //Magic

        Console.WriteLine("There were {0} parameters, as follows:", parameters.Count);
        foreach (var p in parameters)
        {
            Console.WriteLine("{0}={1}", p.Key, p.Value);
        }
    }

    public static void Main()
    {
        someFunction(new { number = 3, text = "SomeText" } );
        someFunction(new { another = 3.14F, example = new DateTime(2017, 12, 15) } );
    }
}
这种方法的主要缺点是不能使用接口或做任何事情来要求某些键存在。此外,还必须使用反射,这需要做更多的工作。如果希望避免这些缺点,可以使用相同的方法,但使用非匿名类型,如下所示:

class SomeFunctionParams
{
    public int Number { get; set; }
    public string Text { get; set; }
}

public static void someFunction(SomeFunctionParams params)
{
    Console.WriteLine("Number={0}", params.Number);
    Console.WriteLine("Text={0}", params.Text);
}
…但这样你就失去了匿名类型的动态优势

另一个选项是将每个可能的键作为可选参数公开,并仅提供所需的键:

void someFunction(int Number = default(int), string Text = default(string), DateTime SomeOtherParam = default(DateTime))
{
    if (Number != default(int)) Console.WriteLine("Number={0}", Number);
    if (Text != default(string)) Console.WriteLine("Text={0}", Text);
    if (SomeOtherParam != default(DateTime)) Console.WriteLine("SomeOtherParam={0}", SomeOtherParam);
}

someFunction(Number : 3, Text : "Some text");
这使得内联初始化更易于阅读:

someFunction(new Dictionary<string, object> {
    ["number"]=3, ["text"]="Some Text"
});
someFunction(新字典){
[“数字”]=3,[“文本”]=“一些文本”
});
那么:

public static void Main()
{
    Iterate(new Dictionary<string, object> { ["1"] = "one", ["2"] = "Two" });
    Console.Read();
}

public static void Iterate(Dictionary<string, object> args)
{
    foreach (var item in args)
    {
        Console.WriteLine("key: " + item.Key + " value: " + item.Value);
    }
}
publicstaticvoidmain()
{
迭代(新字典{[“1”]=“1”,[“2”]=“2”});
Console.Read();
}
公共静态void Iterate(字典参数)
{
foreach(参数中的变量项)
{
Console.WriteLine(“键:+item.key+”值:+item.value);
}
}
您可以在文件开头使用:

using D = System.Collections.Generic.Dictionary<string, object>;


如果所有参数都已知,则使用以下参数会更有效:

和样本使用:

someMethod(d: 1, b: 2);

您可以使用多值字典。。例如
Dictionary
或一个类,在您的情况下,您将只迭代
列表
我认为您不能直接迭代Dictionary,但您可以迭代它的Keys集合。你的字典有性能问题吗?你应该使用一个类…如果你只是需要一些东西来测试,你不应该使用字典来组合字符串和某个对象。这可以通过插入速度不太慢的结构列表来完成。我的问题是调用函数。它需要更多的行,这看起来不太好,因为在php中,我可以在一行中完成所有事情。@ZoharPeled我确实提到:)正确,没有看到,对不起。有一个包可以使用ValueTuple。这个函数很好,但我不能传递整数,只能传递字符串。将第二个字符串更改为object以供其他阅读器使用。@MoDGenesis是的,我更新了它,改为使用string,object(并添加了字符串插值而不是concatation),我个人喜欢它,因为它还确保您不会发送相同的键,而且它看起来最像OP想要的实现。但是,我个人希望看到更多关于此方法的缺点的信息。您还可以说如何从对象类型中选择count()?还有第二个选项,您将失去更改变量名的能力。这种解决方法是传奇式的。似乎如果我想提出它,我需要更多的c#知识,那么我现在有了。(思考等)因此,我为什么问如何做计数()
class SomeFunctionParams
{
    public int Number { get; set; }
    public string Text { get; set; }
}

public static void someFunction(SomeFunctionParams params)
{
    Console.WriteLine("Number={0}", params.Number);
    Console.WriteLine("Text={0}", params.Text);
}
void someFunction(int Number = default(int), string Text = default(string), DateTime SomeOtherParam = default(DateTime))
{
    if (Number != default(int)) Console.WriteLine("Number={0}", Number);
    if (Text != default(string)) Console.WriteLine("Text={0}", Text);
    if (SomeOtherParam != default(DateTime)) Console.WriteLine("SomeOtherParam={0}", SomeOtherParam);
}

someFunction(Number : 3, Text : "Some text");
someFunction(new Dictionary<string, object> {
    ["number"]=3, ["text"]="Some Text"
});
public static void Main()
{
    Iterate(new Dictionary<string, object> { ["1"] = "one", ["2"] = "Two" });
    Console.Read();
}

public static void Iterate(Dictionary<string, object> args)
{
    foreach (var item in args)
    {
        Console.WriteLine("key: " + item.Key + " value: " + item.Value);
    }
}
using D = System.Collections.Generic.Dictionary<string, object>;
using System.Collections.Generic;

Namespace {
    using D = Dictionary<string, object>;
public void someMethod(D args){
   foreach (var item in args){
       Console.WriteLine("key: " + item.Key + " value: " + item.Value);
   }
}
someMethod(new D { { "number", 3 }, { "text", "Some Text" } }));
void someMethod(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0){
    Console.WriteLine($"key: {nameof(a)} value: {a}");
    Console.WriteLine($"key: {nameof(b)} value: {b}");
    // ...
}
someMethod(d: 1, b: 2);