将泛型列表的字段用于类方法中

huangapple go评论77阅读模式
英文:

use field of generic list into class method

问题

我有几个通用列表,它们具有不同数量的属性,但它们都具有一些共同的字段名称,例如 id、port、name 等等。

我有类似下面的代码片段。

public bool LookPortName<T>(List<T> list, string id, ref string port, ref string name)
{
    int index;
    try
    {
        //检查在通用列表中是否找到了 id。
        if (index == -1) return false;
        //获取投资组合缩写。
        port = list[index].portfolio.Trim();
        //获取投资组合完整名称。
        name = list[index].portName.Trim();
        return true;
    }
    catch
    {
        //其他代码
    }
}

所有列表都有共同的字段,如 "id"、"portfolio" 和 "portName",但它们不存在于通用方法中。

是否可能在通用方法中使用通用列表的字段?

有谁知道如何用清晰的代码示例解决我的问题吗?

非常感谢!

英文:

I have several generic lists which have different quantity of properties, but all of them have some
common field names, for instance, id, port, name, and so on.

I have something like snippet.

public bool LookPortName&lt;T&gt;(List&lt;T&gt; list, string id, ref string port, ref string name)  
{
    int index;  
    try
    {    
      //It checks if found id into generic list.  
      if (index == -1) return false;  										
      //Get portfolio abbreviation.  											
      port = list[index].portfolio.Trim();  
      //Get portfolio complete name.  
      name = list[index].portName.Trim();  	
      return true;  
    }
    catch
    {
      //Other code
    }
}  

将泛型列表的字段用于类方法中

All lists have common files such as "id", "portfolio" and "portName" but they doesn't exist into generic
method.

Is it possible to use fields of generic list into generic method?

Someone who knows how to solve my question with a clear code example?

Thanks a lot!

答案1

得分: 3

使用一个接口

// 修改接口以适应您的程序
interface IPortfolio {
    public string Id { get; set; }
    public string portfolio { get; set; }
    public string portName { get; set; }
}

并在方法声明中添加 where T : IPortfolio
这允许您将 T 用作 IPortfolio。

public bool LookPortName<T>(List<T> list, string id, ref string port, ref string name) where T : IPortfolio

然后,任何需要传递到方法中的类都需要实现该接口。

请注意,您不能仅仅使用一个接口,因为您无法传递一个列表。

更多信息

英文:

Use an interface

// modify interface to fit your program
interface IPortfolio {
    public string Id { get; set; }
    public string portfolio { get; set; }
    public string portName { get; set; }
}

and add where T : IPortfolio to the method declaration
This allows you to use T as if it were an IPortfolio.

public bool LookPortName&lt;T&gt;(List&lt;T&gt; list, string id, ref string port, ref string name) where T : IPortfolio

Then, have any class which needs to be passed into the method implement the interface

Note that you can't just use an interface because you wouldn't be able to pass a list.

More Info

答案2

得分: 2

常见的方法是将所有通用的属性/方法提取到接口(或抽象类)中,在相应的类型中实现此接口(或从类继承),然后引入泛型约束来限制允许的类型为接口(或抽象类):

public bool LookPortName<T>(List<T> list, string id, ref string port, ref string name)  
   where T : IHaveFields
{
    T x = ...;
    x.SomePropOnInterface;
}  
英文:

The common approach is to extract all common properties/methods into interface (or abstract class), implement this interface in the corresponding types (or inherit from the class) and then introduce the generic constraint limiting the allowed types to the interface (or abstract class):

public bool LookPortName&lt;T&gt;(List&lt;T&gt; list, string id, ref string port, ref string name)  
   where T : IHaveFields
{
    T x = ...;
    x.SomePropOnInterface;
}  

答案3

得分: 1

就像@AspectOfTheNoob的答案中所提到的,您可以创建接口,在您的项目类中实现它,并在LookPortName方法的T约束中使用它。

public interface IPortInfo {
    string id { get; }
    string portfolio { get; }
    string portName { get; }
}

public class SomeItemPortInfo : IPortInfo {
    public string id { get; set; }
    public string portfolio { get; set; }
    public string portName { get; set; }
}

public bool LookPortName<T>(List<T> list, string id, ref string port, ref string name)
    where T : IPortInfo {

您还可以构建基类并添加约束,或者直接将其用作参数类型。

public abstract class BasePortInfo {
    public virtual string id { get; set; }
    public virtual string portfolio { get; set; }
    public virtual string portName { get; set; }
}

public class SomeItemPortInfo : BasePortInfo {
}

如果需要,您可以将此方法声明为List的扩展方法。

public static class PortInfoListExtensions {
    public static bool TryGetPortInfo<T>(this List<T> list, string id, out string port, out string name) where T : BasePortInfo {        
        port = null; name = null;
        try {
            int index = list.FindIndex(i => i.id == id);
            if (index < 0)
                return false;
            //获取投资组合缩写。                                             
            port = list[index].portfolio.Trim();
            //获取投资组合完整名称。  
            name = list[index].portName.Trim();
            return true;
        } catch {
            return false;
            //其他代码
        }
    }
}

然后,可以像这样调用它:

if (listOfPortInfo?.TryGetPortInfo(id, out string port, out string name) ?? false) {
    //如果列表包含id,则对port和name进行一些操作....
}

如果无法添加接口或更改类定义,您还可以测试参数的类型并使用反射。

英文:

Like in @AspectOfTheNoob answer you can create interface, implement it in your items classes, and use it in constrain of T in LookPortName method .

public interface IPortInfo {
    string id { get; }
    string portfolio { get; }
    string portName { get; }
}
public class SomeItemPortInfo : IPortInfo {
    public string id { get; set; }
    public string portfolio { get; set; }
    public string portName { get; set; }
}

public bool LookPortName&lt;T&gt;(List&lt;T&gt; list, string id, ref string port, ref string name)
    where T : IPortInfo {

You can also build base class and add constrain or use it directly as type of argument.

public abstract class BasePortInfo {
    public virtual string id { get; set; }
    public virtual string portfolio { get; set; }
    public virtual string portName { get; set; }
}

public class SomeItemPortInfo : BasePortInfo {
}

If you need, you can declare this method as extension of List

public static class PortInfoListExtensions {
    public static bool TryGetPortInfo&lt;T&gt;(this List&lt;T&gt; list, string id, out string port, out string name) where T : BasePortInfo {        
        port = null; name = null;
        try {
            int index = list.FindIndex(i =&gt; i.id == id);
            if(index &lt; 0)
                return false;
            //Get portfolio abbreviation.                                             
            port = list[index].portfolio.Trim();
            //Get portfolio complete name.  
            name = list[index].portName.Trim();
            return true;
        } catch {
            return false;
            //Other code
        }
    }
}

And call it, for example like here:

if(listOfPortInfo?.TryGetPortInfo(id, out string port, out string name) ?? false) {
    //if list contains id, do something with port and name....            
}

You can also test type of argument and use reflection, if you can't add inteface or change class definitions.

答案4

得分: -1

另一个选择是将其分配给 dynamic —— 这在编译时不需要显式的类型转换操作,因为它仅在运行时识别类型。

public class GenericListDemoProgram
{
    internal static async Task Main(string[] args)
    {
        await Task.Yield();
        var port = string.Empty;
        var name = string.Empty;

        if (LookPortName(new[]
        {
            new {id = "p1", portfolio = "portfolio1", portName = "8123"},
            new {id = "p2", portfolio = "portfolio2", portName = "8122"},
            new {id = "p3", portfolio = "portfolio3", portName = "8121"},
            new {id = "p4", portfolio = "portfolio4", portName = "8120"},
        }.ToList(), 3, ref port, ref name))
        {
            Console.WriteLine($"port:{port}; name:{name}");
        }
    }

    public static bool LookPortName<T>(List<T> list, int index, ref string port, ref string name)
    {
        try
        {
            // 检查是否在泛型列表中找到了id。  
            if (index == -1) return false;

            dynamic item = list[index];

            if (item == null) return false;

            // 获取投资组合缩写。                                             
            port = item.portfolio.Trim();
            // 获取投资组合完整名称。  
            name = item.portName.Trim();
            return true;
        }
        catch (Exception ex) { 
            // 其他代码
            return false;
        }
    }
}

注意:Dynamic Language Runtime (DLR) 也是这里需要考虑的一点,尤其是在与其他语言进行交互方面(尽管这可能不是您工作的一个方面)。

英文:

Another option here is to assign to dynamic --
which

> doesn’t require explicit cast operations at compile time, because it identifies the type at run time only

public class GenericListDemoProgram
{
    internal static async Task Main(string[] args)
    {
        await Task.Yield();
        var port = string.Empty;
        var name = string.Empty;

        if (LookPortName(new[]
        {
            new {id = &quot;p1&quot;, portfolio = &quot;profolio1&quot;, portName = &quot;8123&quot;},
            new {id = &quot;p2&quot;, portfolio = &quot;profolio2&quot;, portName = &quot;8122&quot;},
            new {id = &quot;p3&quot;, portfolio = &quot;profolio3&quot;, portName = &quot;8121&quot;},
            new {id = &quot;p4&quot;, portfolio = &quot;profolio4&quot;, portName = &quot;8120&quot;},
        }.ToList(), 3, ref port, ref name))
        {
            Console.WriteLine($&quot;port:{port}; name:{name}&quot;);
        }
    }

    public static bool LookPortName&lt;T&gt;(List&lt;T&gt; list, int index, ref string port, ref string name)
    {
        try
        {
            //It checks if found id into generic list.  
            if (index == -1) return false;

            dynamic? item = list[index];

            if (item == null) return false;


            //Get portfolio abbreviation.                                             
            port = item.portfolio.Trim();
            //Get portfolio complete name.  
            name = item.portName.Trim();
            return true;
        }
        catch (Exception ex) { 
            //Other code
            return false;
        }
    }
}

result

将泛型列表的字段用于类方法中


note the Dynamic Language Runtime (DLR) is also a consideration here -- in respect to interoperation (though that may not be an aspect of your work)

huangapple
  • 本文由 发表于 2023年1月9日 04:38:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051103.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定