C# 返回Id的常规函数

C# 返回Id的常规函数,c#,C#,在我的项目中,我编写了自己的地图绘制程序,在很多地方我都在做类似的事情 tbl.Type!=无效的tbl.Type.Id:0返回引用对象的Id。 因为这种情况发生了很多次,所以我试着做一个小函数来为我做这个检查,不管我传递的对象是什么类型的 我当时在想 public static int returnId(object input) { if(input != null && input.Id != null) { return input.Id;

在我的项目中,我编写了自己的地图绘制程序,在很多地方我都在做类似的事情
tbl.Type!=无效的tbl.Type.Id:0
返回引用对象的Id。 因为这种情况发生了很多次,所以我试着做一个小函数来为我做这个检查,不管我传递的对象是什么类型的

我当时在想

public static int returnId(object input)
{
    if(input != null && input.Id != null)
    {
        return input.Id;
    }
    return 0;
}
或者可能使用泛型类型

当前,此函数引发错误,因为
对象
不包含
.Id
的定义。我已经在谷歌上搜索了几个小时,开始怀疑我要找的东西是否可能

欢迎您的任何帮助和想法,我们将不胜感激

所有输入应实现
IId
接口:

public static int returnId(IId input)
{
    if(input != null && input.Id != null)
    {
        return input.Id;
    }
    return 0;
}
或通过反射:

public static int returnId(object input)
{        
    if(input != null)
    {
        var Id = input.GetType().GetProperty("Id").GetValue(input);
        if(Id != null)
            return ((int?)Id).Value;
    }
    return 0;
}
您有两个选择:

1:使用
动态
而不是
对象

public static int returnId(dynamic input)
{
    if(input != null && input.Id != null)
    {
        return input.Id;
    }
    return 0;
}
2:让您的所有类从定义
id
的接口继承:

public static int returnId(IId input)
{
    if(input != null && input.Id != null)
    {
        return input.Id;
    }
    return 0;
}

public interface IId
{
   int Id {get; set;}
}

第二个选项应该具有更好的性能,因为需要在运行时解析操作。

您可以使用继承并为每个类实现
Id
属性。大概是这样的:

public abstract class ObjectId
{
    // Or as auto-propert `public virtual int Id { get; private set; }`.
    public abstract int Id { get; }
}

public class ObjectImpl : ObjectId
{
    public override int Id
    {
        get { return 0; }
    }
}
除了此实现之外,还可以为基类定义默认值(作为虚拟属性)。因此,并非每个类都必须重写属性
Id

使用此实现,您可以将
ObjectId
作为输入类型传递给函数,如果
null
则返回
0

public static int returnId(ObjectId input)
{
    return (input != null) ? input.Id : 0; // input.Id will never be null.
}

你想做的事在一般情况下是不可行的。如果希望能够检索对象的Id,则需要确保在方法中使用的每个类型中都存在属性Id

在大多数情况下,最好的选择是遵循斯拉瓦最初的建议,即(稍加改进)

公共接口IId
{
int Id{get;}
}
公共静态int returnId(T输入),其中T:IId
{
返回输入!=null?输入。Id:0;
}
使用动态和反射(例如input.GetType().GetProperty(“Id”).GetValue(input))会产生类似的效果,但是 1) 它不提供编译时保证-所有验证都在运行时完成,如果类型没有名为“Id”的属性,则验证将失败; 2) 运行时逻辑对性能有负面影响,这在高强度使用期间是显而易见的


正如@hofmeister所建议的,只有当您只需要将此方法应用于您自己定义的类型,而不是任何第三方类时,继承才是一个选项。

是否
object
始终是自定义类型?
object
将是我在C#6中定义的类,您可以使用
tbl.type?.Id??0
我真希望我早知道这一点。是一件事。这样我就省去了很多麻烦。我会用的,谢谢!那里不需要泛型。不错,人们通常看不到接口的需要,当它盯着它们看时,为什么
Id
应该是抽象的?@nozzleman我对派生类一无所知。对于抽象属性,每个类都有自己的实现。是的,我明白了,我假设每个
都可能会使用自动属性来实现它,因此将其设置为
虚拟
自动属性仍然允许在极少数情况下重写它,需要另一个实现。只有
抽象属性的
抽象类
基本上是一个
接口
。除此之外,如果OP选择让所有必需的类实现抽象类,那么抽象类是有意义的;)@确实是nozzleman,但我也提到了默认实现(auto属性)。没有关于对象的任何细节,我们只能猜测最佳实现。
public interface IId
{
    int Id {get;}
}

public static int returnId<T>(T input) where T : IId
{
    return input != null ? input.Id : 0;
}