c# - Force a narrow implicit coercion at compile time -


i'm trying define struct uses variable restricted range of numbers, , implicit coercion ints. i'd able force build errors if constants or other hardcoded values used struct.

here example of i'm trying accomplish.

    byte = 123; // allowed     byte b = 123123; // not allowed     const int x = 123;     const int y = 123123;     byte c = x; // allowed     byte d = y; // not allowed 

i ideally able to, example, restrict number 1 99, mystruct s = 50; works mystruct s = 150; causes compile time error bytes b , d above do.

i found something similar different language, not c#.

i think can using custom attributes , roslyn code analyses. let me sketch solution. should @ least solve first usecase initialize literal.

first need custom attribute applies struct allow code analyses able know valid range:

[attributeusage(system.attributetargets.struct)] public class minmaxsizeattribute : attribute {     public int minval { get; set;}     public int maxval { get; set;}     public minmaxsizeattribute()     {     } } 

what here store min , max value in attribute. way can use later in source code analyses.

now apply attribute struct declaration:

[minmaxsize(minval = 0, maxval = 100)] public struct foo {     //members , implicit conversion operators go here } 

now type information struct foo contains value range. next thing need diagnosticanalyzer analyze code.

public class myanalyzer : diagnosticanalyzer {     internal static diagnosticdescriptor rule = new diagnosticdescriptor("cs00042",          "value not allowed here",         @"type {0} not allow values in range",          "type checker",          diagnosticseverity.error,         isenabledbydefault: true, description: "value big");     public myanalyzer()     {     }      #region implemented abstract members of diagnosticanalyzer      public override void initialize(analysiscontext context)     {         context.registersyntaxnodeaction(analyzesyntaxtree, syntaxkind.simpleassignmentexpression);     }      public override immutablearray<diagnosticdescriptor> supporteddiagnostics => immutablearray.create(rule);      #endregion      private static void analyzesyntaxtree(syntaxnodeanalysiscontext context)     {      } } 

this bare bone skeleton participate in code analyzes. analyzer registers analyze assignments:

context.registersyntaxnodeaction(analyzesyntaxtree, syntaxkind.simpleassignmentexpression); 

for variable declarations need register different syntaxkind simplicity stick 1 here.

lets have @ analyses logic:

private static void analyzesyntaxtree(syntaxnodeanalysiscontext context)         {             if (context.node.iskind(syntaxkind.simpleassignmentexpression))             {                 var assign = (assignmentexpressionsyntax)context.node;                 var lefttype = context.semanticmodel.gettypeinfo(assign.left).gettype();                 var attr = lefttype.getcustomattributes(typeof(minmaxsizeattribute), false).oftype<minmaxsizeattribute>().firstordefault();                 if (attr != null && assign.right.iskind(syntaxkind.numericliteralexpression))                 {                     var numlitteral = (literalexpressionsyntax)assign.right;                     var t = numlitteral.token;                     if (t.value.gettype().equals(typeof(int)))                     {                         var intval = (int)t.value;                         if (intval > attr.maxval || intval < attr.maxval)                         {                             diagnostic.create(rule, assign.getlocation(), lefttype.name);                         }                     }                 }             }         } 

what analyzer is, checking if type on left side has minmaxsize associated , if checks if right side literal. when literal tries integer value , compares minval , maxval associated type. if values exceeds range report diagnostics error.

please note code untested. compiles , passed basic tests. meant illustrate possible solution. further information have @ rsolyn docs

the second case want covers more complex because need apply dataflow analyzes value of x.


Comments

Popular posts from this blog

1111. appearing after print sequence - php -

java - WARN : org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/board/] in DispatcherServlet with name 'appServlet' -

Ruby on Rails, ActiveRecord, Postgres, UTF-8 and ASCII-8BIT encodings -