方法参数(对象)不是类型列表C#

时间:2015-04-10 19:37:52

标签: c# generics

您好我已经看过并需要一些帮助,我使用反射从类中获取值,这些类有一个类似的名称“Name” 我有一个方法

public static void GetName<T>(T Object)
{
    xxxxxxx
}

现在,用户将使用此类方法

var User = .....
var name = GetName(User);

如何仅限用于类对象,因为我想阻止使用List和其他类型 前

List<SystemUsers> users = ..... 
var name = GetName(users) ... this should not be allowable

有没有这样的方法,我尝试放置“class”和“where T:new()”

但它似乎没有做到这一点

请帮助

4 个答案:

答案 0 :(得分:1)

在GetName()方法中,您需要测试对象类型,如果它不是有效类型,则抛出异常。

但是,这并不是一种有效的方法。您可能最好使用界面,这样您就不必担心您不允许的类型 - 因为无效类型的数量可能达到无限限制。

答案 1 :(得分:1)

正如Daniel在原始问题的评论中所述,让每个对象实现一个包含属性的接口,并让您的方法将该接口作为其参数将是限制它的最佳方式,例如:

public static void GetName(IPerson entity) { entity.Name = "Test"; }

答案 2 :(得分:1)

只是为了抛出另一个选项,因为你已经在使用反射,你也可以在传入的对象上使用它来检测它是否有一个名称属性。

但是,这不会给出任何编译时异常,所以你在调用它时必须尝试/ catch,或者让它返回一个空字符串而不是抛出异常(或其他东西......)。 / p>

例如,如果您只想要具有Name属性的对象,则可以执行以下操作:

private static string GetName<T>(T input)
{
    var nameProperty =
        typeof (T)
            .GetProperties()
            .FirstOrDefault(propInfo =>
                propInfo.Name.Equals("Name", StringComparison.OrdinalIgnoreCase));

    if (nameProperty == null)
    {
        throw new InvalidOperationException(
            "The input type does not have a name property");
    }

    return (string) nameProperty.GetValue(input);
}

答案 3 :(得分:0)

你不能。正如评论中所述,List<> 一个类。将其限制为类将包括它。

这是一个不幸的情况,你可能只需依靠调用代码时使用的契约,并为无效的参数抛出异常。

public static string GetName<T>(T Object)
{
    if(Object is IEnumerable) throw new ArgumentException();
    xxxxxxx
}

另一种选择可能是添加一个IEnumerable的重载。它不是很漂亮,你可能不需要它,但至少编译器会选择它并返回适当的东西。

public static IEnumerable<string> GetName<T>(IEnumerable<T> Objects)
{
    return Objects.Select(GetName);
}

但要小心,因为有时候很难预测(或者更确切地说,要记住预测)将会调用哪一个。

List<int> ints = new List<int>();

GetName(ints); // calls the IEnumerable version

object intsObj = (object)ints;
GetName(intsObj); // calls the non-IEnumerable version.

但更一般地说,听起来你可能会在这里建立一个不太理想的合同。如果您使用未经过滤的仿制药做这样的事情,您可能也希望能够处理其中的集合,事实上我不确定为什么您不能至。他们像其他任何东西一样反对。

如果 试图限制它,您可能需要一个接口或基类,必须从该接口或基类继承传递给此方法的所有对象。这将大大减少你传递.NET类的选择,但我无法想象如果你需要得到一个&#34;名称&#34;来自某事。

如果你去那条路线,你有两个选择:

  • 限制参数本身
  • 限制通用参数

那里的选择取决于方法的内容和返回类型,但我可能会选择前者。

public static string GetName<T>(IObjectWithName Object)
{
    return Object.Name;
}
但是,作为一个例子,这并不是特别有趣,所以这就是你如何限制泛型。

public static string GetName<T>(T Object)
    where T : IObjectWithName
{
    return Object.Name;
}

请记住,您的对象需要实现该界面 - 例如,您无法将DateTime传递给此方法并期望它能够正常工作。如果你期望&#34;随机&#34;像这样输入,你可能需要自己设置接收集合类型。


我应该提一下,仅仅为了良好的练习,命名参数Object不是一个好习惯。这是C#中的关键字(或者说是系统级类型)。所以你最终可能会遇到冲突。