C#模板选项

时间:2015-04-03 16:41:00

标签: c# templates collections

我正在尝试做一些适用于C ++的事情,但C#对我来说是一个挑战。

我有一个方法可以进行一些解析,数据库访问,Web访问/等等,最终会有一系列字符串添加到容器中。有时我需要将它添加到哈希集或列表等。

所以,在c ++中,这看起来像这样:

<template T>
bool GetStrings(T& container)
{
    ...
    std::string foo = "bar";
    ...
    container.add(foo);  // This statement is within a loop and if checks
    ...
    return true;
}

我在C#中试过了:

private bool GetStrings<T>(ref T cont)
{
    string foo = "BAR";
    cont.Add(foo); // T does not contain a definition for Add ...
    return true;
}

同事建议使用容器的基类/接口。所以,我尝试了这个(在看到List,Hashset等之后有一个共同的接口定义):

private bool GetStrings(ref ICollection<string> cont)
{
    string foo = "BAR";
    cont.Add(foo);
    return true;
}

我希望能够像这样调用这个方法:

HashSet<string> a = new HashSet<string>();
List<string> b = new List<string>();
// etc other classes containing "Add" method
if (GetString(ref a)) ...  // These aren't all in one place, but spread out
if (GetString(ref b)) ...  // and the types are based on what is useful in
if (GetString(ref c)) ...  // each particular context.
if (GetString(ref d)) ...

现在方法本身编译,但我无法调用它。我得到Best过载有无效的参数,“参数1:无法从'ref System.Collections.Generic.List'转换为'ref System.Collections.Generic.ICollection'”

我认为它只是一种类型转换需要的东西。所以,我试试:

if (GetString(ref (ICollection<string>)a)) ...

然后我得到“ref或out参数必须是可赋值变量”。所以,问题是......这可以在C#中完成吗,我是否完全走错了路?我还研究了传递一个Object ref并尝试调用'GetType'和'GetMethod'等来确定Add是否可用等等但是无法弄清楚如何调用Add方法。

2 个答案:

答案 0 :(得分:1)

使用generic type constraints。 您可以执行以下编译和运行:

class Program
{
    static void Main(string[] args)
    {
        Test t = new Test();

        HashSet<string> a = new HashSet<string>();
        List<string> b = new List<string>();

        if (t.GetString(ref a))
        {

        }
        if (t.GetString(ref b))
        {

        }
    }

    public class Test
    {
        public bool GetString<T>(ref T cont) where T : ICollection<string>
        {
            string foo = "BAR";
            cont.Add(foo);
            return true;
        }
    }
}

顺便说一下,所有集合都已经是引用类型,除非你想要更改原始变量,否则ref不是必需的。请参阅here for an explanation

答案 1 :(得分:0)

您需要在方法上使用通用约束:

private bool GetStrings<T>(T cont) where T : ICollection<string>
{
    string foo = "BAR";
    // The compiler knows that T is always ICollection<string>, and can infer that Add
    // is a valid method call
    cont.Add(foo);
    return true;
}

此外,您不需要通过引用传递您的列表 - 它已经是一个参考。用C ++的说法,它就像你将指针传递给那里的指针一样。