Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 接受自身字段参数的C接口或抽象类_C#_.net_Interface_Abstract Class - Fatal编程技术网

C# 接受自身字段参数的C接口或抽象类

C# 接受自身字段参数的C接口或抽象类,c#,.net,interface,abstract-class,C#,.net,Interface,Abstract Class,我试图创建一个接口或抽象类,作为许多授权对象的基础 我的想法如下:代码不编译,但我想工作: public abstract class AuthObject { public Enum Values; public abstract AuthObject AddPermission(Values permission); } 实现如下所示: public class AuditLogManagement : AuthObject { private long _permission

我试图创建一个接口或抽象类,作为许多授权对象的基础

我的想法如下:代码不编译,但我想工作:

public abstract class AuthObject {
  public Enum Values;
  public abstract AuthObject AddPermission(Values permission);
}
实现如下所示:

public class AuditLogManagement : AuthObject {
  private long _permissions;

  public new enum Values {
    None = 0,
    Read = 1,
    Search = 2,
    Filter = 4,
    Export = 8
  }

  public AuthObject AddPermission(AuditLogManagement.Values permission) {
    _permissions |= (long)permission;
    return this;
  }
}
我的问题的要点是如何将参数AddPermission限制为接口或抽象类中仅此对象值字段Enum。然而,我找不到一个方法来做这件事

谢谢你的建议

编辑:

更简单一点的用例来解释需求:

interface I {
  AddPermission(I.Values permission);
}

class A : I {
  private long _permissions;

  public enum Values {
    A_a, A_b, A_c
  }
  AddPermission (this.Values newPermission) {
    _permissions |= newPermission;
  }
}

class B : I {
  private long _permissions;

  public enum Values {
    B_a, B_b, B_c
  }
  AddPermission (this.Values newPermission) {
    _permissions |= newPermission;
  }
}

var classA = new A();
var classB = new B();
A.AddPermission(A.Values.A_a); // Allowed
A.AddPermission(B.Values.B_c); // Forbidden! B_c value equals to A_c but is not the same permission!

也许你可以使用泛型

public abstract class AuthObject<T>
{
    public abstract AuthObject<T> AddPermission(T permission);
}

public class AuditLogManagement : AuthObject<Values>
{
    private Values _permissions;

    public override AuthObject<Values> AddPermission(Values permission)
    {
        _permissions |= permission;
        return this;
    }
}

[Flags]
public enum Values
{
    None = 0,
    Read = 1,
    Search = 2,
    Filter = 4,
    Export = 8
}
你有三个打字错误

这里的值是在AuditLogManagement类中定义的。每当您想在AuditLogManagement之外使用该数据类型时,它都需要是AuditLogManagement.Values

这是正确的代码:

public abstract class AuthObject {
  public Enum Values;
  public abstract AuthObject AddPermission(AuditLogManagement.Values permission);
}
public override AuthObject AddPermission(AuditLogManagement.Values permission)
管理类中的AddPermission方法不会重写抽象基方法

正确代码:

public abstract class AuthObject {
  public Enum Values;
  public abstract AuthObject AddPermission(AuditLogManagement.Values permission);
}
public override AuthObject AddPermission(AuditLogManagement.Values permission)
旁注:审计日志管理。这里没有必要

您在末尾拼错了变量no:

_permissions |= (long)permission;

1:如果有人想以打字错误结束问题,请告诉我您没有正确声明枚举类型

public enum Values {
    None = 0,
    Read = 1,
    Search = 2,
    Filter = 4,
    Export = 8
}

public abstract class AuthObject {
  public Values Value;
  public abstract AuthObject AddPermission(Values permission);
}

public class AuditLogManagement : AuthObject {
  private long _permissions;
  private Values _values;

  public override AuthObject AddPermission(Values permission) {
    _permissions |= (long)permission;
    return this;
  }
}

我会选择仿制药:

public abstract class AuthObject<T>
     where T : struct, IConvertible // A reasonable way to constrain to an enumeration. 
                                    // you can also use System.Enum for newer versions of C# past 7.3 I believe. 
{
    public T Values { get; } 
    public abstract AuthObject<T> AddPermission(T permission);
}

public enum Values
{
    None = 0,
    Read = 1,
    Search = 2,
    Filter = 4,
    Export = 8
}

public class AuditLogManagement : AuthObject<Values>
{
    private long _permissions;
    public AuthObject AddPermission(Values permission)
    {
        _permissions |= (long)permissions;
        return this;
    }
}

除此之外,我给出的另一个建议是将上面的“T”参数命名为更具描述性的名称,例如“TPermission”,因为您没有将其用于典型的容器类

第一个代码块如何不编译?如果我用字符串替换值,它对我有效。基类AuthObject的作用是什么?这就是问题的关键。接口或抽象类必须强制继承/实现类的方法只接受自己的枚举。想象一下,第二个名为UserManagement的方法实现了相同的接口/抽象类。必须禁止执行var um=new UserManagement.AddPermissionAuditLogManagement.Values.Read;将AuditLogManagement枚举值传递给UserManagement类对象违反了安全规则。我想使用接口或抽象类强制执行规则。AuthObject是一个抽象类。每个实现可以并且可能将在值字段中包含不同的枚举值集。例如,AuditLogManagement可以具有读取、导出等功能,但UserManagement对象可能具有CreateUser、UpdateUser、DeleteUser枚举值。虽然基础int-valuetypes可能等于AuditLogManagement.Read=1==UserManagement.CreateUser=1,但允许将AuditLogManagement.Read-as参数传递给UserManagement.AddPermission是一个缺陷。这正是我不需要的。通过在抽象类或接口中指定AuditLogManagement.Values,您将在所有实现中仅将参数限制为该枚举。该要求声明该方法必须接受自己的父类值类型。