简体   繁体   English

将 int 或 string 作为泛型类型传递并在可空和不可空属性中使用的接口

[英]Interface passing int or string as generic type and using in nullable and not nullable properties

I'm trying to do a Interface for property changes in a product.我正在尝试为产品中的属性更改做一个接口。 In some case the values are int others the values would by string .在某些情况下,这些值是int其他值,这些值将是string The new value is required, but sometimes the field don't have a old value.新值是必需的,但有时该字段没有旧值。

Something like this:像这样的东西:

public interface IChangeSuggestion<TValue> {
    TValue? OldValue { get; set; } //Line with error
    TValue NewValue { get; set; }
}

public class ChangeSuggestionSomeId : IChangeSuggestion<int> {
    public int? OldValue { get; set; }
    public int NewValue { get; set; }
}

public class ChangeSuggestionName : IChangeSuggestion<string> {
    public string OldValue { get; set; }
    public string NewValue { get; set; }
}

the code above throw the error: A nullable type parameter must be known to be a value type or non-nullable reference type.上面的代码抛出错误:必须知道可以为空的类型参数是值类型或不可为空的引用类型。 Consider adding a 'class', 'struct', or type constraint.考虑添加“类”、“结构”或类型约束。

Edit编辑

I'm using the interface because a shared approval logic, and the classes are Models for the Entity Framework我使用该接口是因为共享批准逻辑,并且这些类是实体框架的模型

To make work in the Entity Framework the follow code do the trick:为了在实体框架中工作,下面的代码可以解决问题:

public interface IChangeSuggestion<TValue> {
    TValue OldValue { get; set; }
    [Required]
    TValue NewValue { get; set; }
    
    int Id { get; set; }
    int ProductId { get; set; }
    bool? Approved { get; set; }
    DateTime? ApprovedOn { get; set; }
    string ApprovedById { get; set; }
}

public class ChangeSuggestionSomeId : IChangeSuggestion<int?> {
    public int? OldValue { get; set; }
    [Required]
    public int? NewValue { get; set; }

    public int Id { get; set; }
    public int ProductId { get; set; }
    public bool? Approved { get; set; }
    public DateTime? ApprovedOn { get; set; }
    public string ApprovedById { get; set; }
}

This works because i'm using Entity Framework that run a validate on SaveChanges, but i think that strictly NewValue should be a int not a int?这是有效的,因为我使用的是在 SaveChanges 上运行验证的实体框架,但我认为严格来说 NewValue 应该是 int 而不是 int?

If you can make sure the TValue just would be int , bool , or other value types, you can use where TValue: struct .如果您可以确保TValue只是intbool或其他值类型,则可以使用where TValue: struct Or where TValue: class for just reference types.或者where TValue: class仅用于引用类型。

public interface ChangeSuggestion<TValue> where TValue : struct
{
    TValue? OldValue { get; set; }
    TValue NewValue { get; set; }
}

Otherwise, you can only use two interfaces with different names (one for value type, one for reference type).否则,您只能使用两个不同名称的接口(一个用于值类型,一个用于引用类型)。 Or use another more complex solution.或者使用另一个更复杂的解决方案。

Here's my guess.这是我的猜测。

I assume you know about there's two kind of types including value type (struct) and reference type.我假设您知道有两种类型,包括值类型(结构)和引用类型。
I think what you really want to ask is now that C# support nullable value type, why we can't use TValue?我想你真正想问的是现在 C# 支持可空值类型,为什么我们不能使用TValue? , I think that's because, in theory, value type variable which points to the stack can't be null, but sometimes we do need it to be nullable. ,我认为这是因为,理论上,指向堆栈的值类型变量不能是 null,但有时我们确实需要它可以为空。 To achieve this, the compiler will make some preprocess during compiling if a value type variable marked as nullable, but a reference type doesn't need this 'preprocess' to be nullable, so we must tell the compiler which type the TValue is then the compiler can decide to do or not do this 'preprocess'.为了实现这一点,如果值类型变量标记为可空值,编译器将在编译期间进行一些预处理,但引用类型不需要此“预处理”为可空值,因此我们必须告诉编译器TValue是哪种类型编译器可以决定做或不做这个“预处理”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM