What is the best approach or alternative to constant references?












2















For the purposes of this question, a 'constant reference' is a reference to an object from which you cannot call methods that modify the object or modify it's properties.



I want something like this:



Const<User> user = provider.GetUser(); // Gets a constant reference to an "User" object
var name = user.GetName(); // Ok. Doesn't modify the object
user.SetName("New value"); // <- Error. Shouldn't be able to modify the object


Ideally, I would mark with a custom attribute (e.g. [Constant]) every method of a class that doesn't modify the instance, and only those methods can be called from the constant reference. Calls to other methods would result in an error, if possible, during compile time.



The idea is I can return a read-only reference to and be sure that it will not be modified by the client.










share|improve this question

























  • This is called "const- correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.

    – Dai
    Nov 25 '18 at 1:20













  • It is actually an immutable.

    – Chris
    Nov 25 '18 at 1:23











  • If you make all properties virtual, you can emit proxies while inheriting from the same object. In this case you can in fact do User u = prov.GetUser(); // gets proxy

    – T.S.
    Nov 25 '18 at 1:31











  • @T.S. overridden virtual properties cannot remove property setters which means you won't get a compiler warning, even if the overridden setter throws NotSupportedException.

    – Dai
    Nov 25 '18 at 2:09











  • @Dai That is correct. Can't be removed. But OP said: "Calls to other methods would result in an error, if possible, during compile time." So, my suggestion is valid. I like it because it is not "way too complex", to emit proxy from the class it inherits

    – T.S.
    Nov 25 '18 at 15:44


















2















For the purposes of this question, a 'constant reference' is a reference to an object from which you cannot call methods that modify the object or modify it's properties.



I want something like this:



Const<User> user = provider.GetUser(); // Gets a constant reference to an "User" object
var name = user.GetName(); // Ok. Doesn't modify the object
user.SetName("New value"); // <- Error. Shouldn't be able to modify the object


Ideally, I would mark with a custom attribute (e.g. [Constant]) every method of a class that doesn't modify the instance, and only those methods can be called from the constant reference. Calls to other methods would result in an error, if possible, during compile time.



The idea is I can return a read-only reference to and be sure that it will not be modified by the client.










share|improve this question

























  • This is called "const- correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.

    – Dai
    Nov 25 '18 at 1:20













  • It is actually an immutable.

    – Chris
    Nov 25 '18 at 1:23











  • If you make all properties virtual, you can emit proxies while inheriting from the same object. In this case you can in fact do User u = prov.GetUser(); // gets proxy

    – T.S.
    Nov 25 '18 at 1:31











  • @T.S. overridden virtual properties cannot remove property setters which means you won't get a compiler warning, even if the overridden setter throws NotSupportedException.

    – Dai
    Nov 25 '18 at 2:09











  • @Dai That is correct. Can't be removed. But OP said: "Calls to other methods would result in an error, if possible, during compile time." So, my suggestion is valid. I like it because it is not "way too complex", to emit proxy from the class it inherits

    – T.S.
    Nov 25 '18 at 15:44
















2












2








2








For the purposes of this question, a 'constant reference' is a reference to an object from which you cannot call methods that modify the object or modify it's properties.



I want something like this:



Const<User> user = provider.GetUser(); // Gets a constant reference to an "User" object
var name = user.GetName(); // Ok. Doesn't modify the object
user.SetName("New value"); // <- Error. Shouldn't be able to modify the object


Ideally, I would mark with a custom attribute (e.g. [Constant]) every method of a class that doesn't modify the instance, and only those methods can be called from the constant reference. Calls to other methods would result in an error, if possible, during compile time.



The idea is I can return a read-only reference to and be sure that it will not be modified by the client.










share|improve this question
















For the purposes of this question, a 'constant reference' is a reference to an object from which you cannot call methods that modify the object or modify it's properties.



I want something like this:



Const<User> user = provider.GetUser(); // Gets a constant reference to an "User" object
var name = user.GetName(); // Ok. Doesn't modify the object
user.SetName("New value"); // <- Error. Shouldn't be able to modify the object


Ideally, I would mark with a custom attribute (e.g. [Constant]) every method of a class that doesn't modify the instance, and only those methods can be called from the constant reference. Calls to other methods would result in an error, if possible, during compile time.



The idea is I can return a read-only reference to and be sure that it will not be modified by the client.







c# const-correctness compile-time-constant






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 25 '18 at 11:59







Leonardo Raele

















asked Nov 25 '18 at 1:17









Leonardo RaeleLeonardo Raele

5901923




5901923













  • This is called "const- correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.

    – Dai
    Nov 25 '18 at 1:20













  • It is actually an immutable.

    – Chris
    Nov 25 '18 at 1:23











  • If you make all properties virtual, you can emit proxies while inheriting from the same object. In this case you can in fact do User u = prov.GetUser(); // gets proxy

    – T.S.
    Nov 25 '18 at 1:31











  • @T.S. overridden virtual properties cannot remove property setters which means you won't get a compiler warning, even if the overridden setter throws NotSupportedException.

    – Dai
    Nov 25 '18 at 2:09











  • @Dai That is correct. Can't be removed. But OP said: "Calls to other methods would result in an error, if possible, during compile time." So, my suggestion is valid. I like it because it is not "way too complex", to emit proxy from the class it inherits

    – T.S.
    Nov 25 '18 at 15:44





















  • This is called "const- correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.

    – Dai
    Nov 25 '18 at 1:20













  • It is actually an immutable.

    – Chris
    Nov 25 '18 at 1:23











  • If you make all properties virtual, you can emit proxies while inheriting from the same object. In this case you can in fact do User u = prov.GetUser(); // gets proxy

    – T.S.
    Nov 25 '18 at 1:31











  • @T.S. overridden virtual properties cannot remove property setters which means you won't get a compiler warning, even if the overridden setter throws NotSupportedException.

    – Dai
    Nov 25 '18 at 2:09











  • @Dai That is correct. Can't be removed. But OP said: "Calls to other methods would result in an error, if possible, during compile time." So, my suggestion is valid. I like it because it is not "way too complex", to emit proxy from the class it inherits

    – T.S.
    Nov 25 '18 at 15:44



















This is called "const- correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.

– Dai
Nov 25 '18 at 1:20







This is called "const- correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.

– Dai
Nov 25 '18 at 1:20















It is actually an immutable.

– Chris
Nov 25 '18 at 1:23





It is actually an immutable.

– Chris
Nov 25 '18 at 1:23













If you make all properties virtual, you can emit proxies while inheriting from the same object. In this case you can in fact do User u = prov.GetUser(); // gets proxy

– T.S.
Nov 25 '18 at 1:31





If you make all properties virtual, you can emit proxies while inheriting from the same object. In this case you can in fact do User u = prov.GetUser(); // gets proxy

– T.S.
Nov 25 '18 at 1:31













@T.S. overridden virtual properties cannot remove property setters which means you won't get a compiler warning, even if the overridden setter throws NotSupportedException.

– Dai
Nov 25 '18 at 2:09





@T.S. overridden virtual properties cannot remove property setters which means you won't get a compiler warning, even if the overridden setter throws NotSupportedException.

– Dai
Nov 25 '18 at 2:09













@Dai That is correct. Can't be removed. But OP said: "Calls to other methods would result in an error, if possible, during compile time." So, my suggestion is valid. I like it because it is not "way too complex", to emit proxy from the class it inherits

– T.S.
Nov 25 '18 at 15:44







@Dai That is correct. Can't be removed. But OP said: "Calls to other methods would result in an error, if possible, during compile time." So, my suggestion is valid. I like it because it is not "way too complex", to emit proxy from the class it inherits

– T.S.
Nov 25 '18 at 15:44














2 Answers
2






active

oldest

votes


















5














The technique you're referring to is called "const-correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.



Alternatively, there's a much simpler solution using interfaces: because C# (and I think the CLR too) does not support const-correctness (the closest we have is the readonly field modifier) the .NET base-class-library designers added "read-only interfaces" to common mutable types to allow a object (wheather mutable or immutable) to expose its functionality via an interface that only exposes immutable operations. Some examples include IReadOnlyList<T>, IReadOnlyCollection<T>, IReadOnlyDictionary<T> - while these are all enumerable types the technique is good for singular objects too.



This design has the advantage of working in any language that supports interfaces but not const-correctness.




  1. For each type (class, struct, etc) in your project that needs to expose data without risk of being changed - or any immutable operations then create an immutable interface.

  2. Modify your consuming code to use these interfaces instead of the concrete type.


Like so:



Supposing we have a mutable class User and a consuming service:



public class User
{
public String UserName { get; set; }

public Byte PasswordHash { get; set; }
public Byte PasswordSalt { get; set; }

public Boolean ValidatePassword(String inputPassword)
{
Hash inputHash = Crypto.GetHash( inputPassword, this.PasswordSalt );
return Crypto.CompareHashes( this.PasswordHash, inputHash );
}

public void ResetSalt()
{
this.PasswordSalt = Crypto.GetRandomBytes( 16 );
}
}

public static void DoReadOnlyStuffWithUser( User user )
{
...
}

public static void WriteStuffToUser( User user )
{
...
}


Then make an immutable interface:



public interface IReadOnlyUser
{
// Note that the interfaces' properties lack setters.
String UserName { get; }
IReadOnlyList<Byte> PasswordHash { get; }
IReadOnlyList<Byte> PasswordSalt { get; }

// ValidatePassword does not mutate state so it's exposed
Boolean ValidatePassword(String inputPassword);

// But ResetSalt is not exposed because it mutates instance state
}


Then modify your User class and consumers:



public class User : IReadOnlyUser
{
// (same as before, except need to expose IReadOnlyList<Byte> versions of array properties:
IReadOnlyList<Byte> IReadOnlyUser.PasswordHash => this.PasswordHash;
IReadOnlyList<Byte> IReadOnlyUser.PasswordSalt => this.PasswordSalt;
}

public static void DoReadOnlyStuffWithUser( IReadOnlyUser user )
{
...
}

// This method still uses `User` instead of `IReadOnlyUser` because it mutates the instance.
public static void WriteStuffToUser( User user )
{
...
}





share|improve this answer





















  • 3





    Side note: interfaces alone will not protect from un-friendly caller as they can use reflection/cast/dynamic to call SetXxxx methods of the implementing class. If this is the case you need both - interfaces and proxy implementation that hides the actual class.

    – Alexei Levenkov
    Nov 25 '18 at 2:06






  • 3





    @AlexeiLevenkov That's no-different to using const_cast in C++ though. I don't think it's worth developing countermeasures to adversarial library consumers anyway, as this is about eliminating potential bugs, not security.

    – Dai
    Nov 25 '18 at 2:12













  • Indeed in case of friendly client interfaces are enough. It is unclear how much protection OP is looking for "be sure that it will not be modified by the client" can be read in many different ways.

    – Alexei Levenkov
    Nov 25 '18 at 2:48











  • @Alexei Levenkov My intent with this is as Dai said, more related to preventing potential bugs than security. Sorry for not being entirely clear. Good observation nonetheless.

    – Leonardo Raele
    Nov 25 '18 at 13:27



















0














So, these are the first two ideas I initially had, but don't quite solve the problem.



Using Dynamic Objects:



The first idea I had was creating a Dynamic Object that would intercept all member invokations and throw an error if the method being called isn't marked with a [Constant] custom attribute. This approach is problematic because a) We don't have the support of the compiler to check for errors in the code (i.e. method name typos) when dealing with dynamic objects, which might lead to a lot of runtime errors; and b) I intend to use this a lot, and searching for method names by name every time a method is called might have considerable performance impact.



Using RealProxy:



My second idea was using a RealProxy to wrap the real object and validate the methods being called, but this only works with objects that inherit from MarshalByRefObject.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53463876%2fwhat-is-the-best-approach-or-alternative-to-constant-references%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    5














    The technique you're referring to is called "const-correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.



    Alternatively, there's a much simpler solution using interfaces: because C# (and I think the CLR too) does not support const-correctness (the closest we have is the readonly field modifier) the .NET base-class-library designers added "read-only interfaces" to common mutable types to allow a object (wheather mutable or immutable) to expose its functionality via an interface that only exposes immutable operations. Some examples include IReadOnlyList<T>, IReadOnlyCollection<T>, IReadOnlyDictionary<T> - while these are all enumerable types the technique is good for singular objects too.



    This design has the advantage of working in any language that supports interfaces but not const-correctness.




    1. For each type (class, struct, etc) in your project that needs to expose data without risk of being changed - or any immutable operations then create an immutable interface.

    2. Modify your consuming code to use these interfaces instead of the concrete type.


    Like so:



    Supposing we have a mutable class User and a consuming service:



    public class User
    {
    public String UserName { get; set; }

    public Byte PasswordHash { get; set; }
    public Byte PasswordSalt { get; set; }

    public Boolean ValidatePassword(String inputPassword)
    {
    Hash inputHash = Crypto.GetHash( inputPassword, this.PasswordSalt );
    return Crypto.CompareHashes( this.PasswordHash, inputHash );
    }

    public void ResetSalt()
    {
    this.PasswordSalt = Crypto.GetRandomBytes( 16 );
    }
    }

    public static void DoReadOnlyStuffWithUser( User user )
    {
    ...
    }

    public static void WriteStuffToUser( User user )
    {
    ...
    }


    Then make an immutable interface:



    public interface IReadOnlyUser
    {
    // Note that the interfaces' properties lack setters.
    String UserName { get; }
    IReadOnlyList<Byte> PasswordHash { get; }
    IReadOnlyList<Byte> PasswordSalt { get; }

    // ValidatePassword does not mutate state so it's exposed
    Boolean ValidatePassword(String inputPassword);

    // But ResetSalt is not exposed because it mutates instance state
    }


    Then modify your User class and consumers:



    public class User : IReadOnlyUser
    {
    // (same as before, except need to expose IReadOnlyList<Byte> versions of array properties:
    IReadOnlyList<Byte> IReadOnlyUser.PasswordHash => this.PasswordHash;
    IReadOnlyList<Byte> IReadOnlyUser.PasswordSalt => this.PasswordSalt;
    }

    public static void DoReadOnlyStuffWithUser( IReadOnlyUser user )
    {
    ...
    }

    // This method still uses `User` instead of `IReadOnlyUser` because it mutates the instance.
    public static void WriteStuffToUser( User user )
    {
    ...
    }





    share|improve this answer





















    • 3





      Side note: interfaces alone will not protect from un-friendly caller as they can use reflection/cast/dynamic to call SetXxxx methods of the implementing class. If this is the case you need both - interfaces and proxy implementation that hides the actual class.

      – Alexei Levenkov
      Nov 25 '18 at 2:06






    • 3





      @AlexeiLevenkov That's no-different to using const_cast in C++ though. I don't think it's worth developing countermeasures to adversarial library consumers anyway, as this is about eliminating potential bugs, not security.

      – Dai
      Nov 25 '18 at 2:12













    • Indeed in case of friendly client interfaces are enough. It is unclear how much protection OP is looking for "be sure that it will not be modified by the client" can be read in many different ways.

      – Alexei Levenkov
      Nov 25 '18 at 2:48











    • @Alexei Levenkov My intent with this is as Dai said, more related to preventing potential bugs than security. Sorry for not being entirely clear. Good observation nonetheless.

      – Leonardo Raele
      Nov 25 '18 at 13:27
















    5














    The technique you're referring to is called "const-correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.



    Alternatively, there's a much simpler solution using interfaces: because C# (and I think the CLR too) does not support const-correctness (the closest we have is the readonly field modifier) the .NET base-class-library designers added "read-only interfaces" to common mutable types to allow a object (wheather mutable or immutable) to expose its functionality via an interface that only exposes immutable operations. Some examples include IReadOnlyList<T>, IReadOnlyCollection<T>, IReadOnlyDictionary<T> - while these are all enumerable types the technique is good for singular objects too.



    This design has the advantage of working in any language that supports interfaces but not const-correctness.




    1. For each type (class, struct, etc) in your project that needs to expose data without risk of being changed - or any immutable operations then create an immutable interface.

    2. Modify your consuming code to use these interfaces instead of the concrete type.


    Like so:



    Supposing we have a mutable class User and a consuming service:



    public class User
    {
    public String UserName { get; set; }

    public Byte PasswordHash { get; set; }
    public Byte PasswordSalt { get; set; }

    public Boolean ValidatePassword(String inputPassword)
    {
    Hash inputHash = Crypto.GetHash( inputPassword, this.PasswordSalt );
    return Crypto.CompareHashes( this.PasswordHash, inputHash );
    }

    public void ResetSalt()
    {
    this.PasswordSalt = Crypto.GetRandomBytes( 16 );
    }
    }

    public static void DoReadOnlyStuffWithUser( User user )
    {
    ...
    }

    public static void WriteStuffToUser( User user )
    {
    ...
    }


    Then make an immutable interface:



    public interface IReadOnlyUser
    {
    // Note that the interfaces' properties lack setters.
    String UserName { get; }
    IReadOnlyList<Byte> PasswordHash { get; }
    IReadOnlyList<Byte> PasswordSalt { get; }

    // ValidatePassword does not mutate state so it's exposed
    Boolean ValidatePassword(String inputPassword);

    // But ResetSalt is not exposed because it mutates instance state
    }


    Then modify your User class and consumers:



    public class User : IReadOnlyUser
    {
    // (same as before, except need to expose IReadOnlyList<Byte> versions of array properties:
    IReadOnlyList<Byte> IReadOnlyUser.PasswordHash => this.PasswordHash;
    IReadOnlyList<Byte> IReadOnlyUser.PasswordSalt => this.PasswordSalt;
    }

    public static void DoReadOnlyStuffWithUser( IReadOnlyUser user )
    {
    ...
    }

    // This method still uses `User` instead of `IReadOnlyUser` because it mutates the instance.
    public static void WriteStuffToUser( User user )
    {
    ...
    }





    share|improve this answer





















    • 3





      Side note: interfaces alone will not protect from un-friendly caller as they can use reflection/cast/dynamic to call SetXxxx methods of the implementing class. If this is the case you need both - interfaces and proxy implementation that hides the actual class.

      – Alexei Levenkov
      Nov 25 '18 at 2:06






    • 3





      @AlexeiLevenkov That's no-different to using const_cast in C++ though. I don't think it's worth developing countermeasures to adversarial library consumers anyway, as this is about eliminating potential bugs, not security.

      – Dai
      Nov 25 '18 at 2:12













    • Indeed in case of friendly client interfaces are enough. It is unclear how much protection OP is looking for "be sure that it will not be modified by the client" can be read in many different ways.

      – Alexei Levenkov
      Nov 25 '18 at 2:48











    • @Alexei Levenkov My intent with this is as Dai said, more related to preventing potential bugs than security. Sorry for not being entirely clear. Good observation nonetheless.

      – Leonardo Raele
      Nov 25 '18 at 13:27














    5












    5








    5







    The technique you're referring to is called "const-correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.



    Alternatively, there's a much simpler solution using interfaces: because C# (and I think the CLR too) does not support const-correctness (the closest we have is the readonly field modifier) the .NET base-class-library designers added "read-only interfaces" to common mutable types to allow a object (wheather mutable or immutable) to expose its functionality via an interface that only exposes immutable operations. Some examples include IReadOnlyList<T>, IReadOnlyCollection<T>, IReadOnlyDictionary<T> - while these are all enumerable types the technique is good for singular objects too.



    This design has the advantage of working in any language that supports interfaces but not const-correctness.




    1. For each type (class, struct, etc) in your project that needs to expose data without risk of being changed - or any immutable operations then create an immutable interface.

    2. Modify your consuming code to use these interfaces instead of the concrete type.


    Like so:



    Supposing we have a mutable class User and a consuming service:



    public class User
    {
    public String UserName { get; set; }

    public Byte PasswordHash { get; set; }
    public Byte PasswordSalt { get; set; }

    public Boolean ValidatePassword(String inputPassword)
    {
    Hash inputHash = Crypto.GetHash( inputPassword, this.PasswordSalt );
    return Crypto.CompareHashes( this.PasswordHash, inputHash );
    }

    public void ResetSalt()
    {
    this.PasswordSalt = Crypto.GetRandomBytes( 16 );
    }
    }

    public static void DoReadOnlyStuffWithUser( User user )
    {
    ...
    }

    public static void WriteStuffToUser( User user )
    {
    ...
    }


    Then make an immutable interface:



    public interface IReadOnlyUser
    {
    // Note that the interfaces' properties lack setters.
    String UserName { get; }
    IReadOnlyList<Byte> PasswordHash { get; }
    IReadOnlyList<Byte> PasswordSalt { get; }

    // ValidatePassword does not mutate state so it's exposed
    Boolean ValidatePassword(String inputPassword);

    // But ResetSalt is not exposed because it mutates instance state
    }


    Then modify your User class and consumers:



    public class User : IReadOnlyUser
    {
    // (same as before, except need to expose IReadOnlyList<Byte> versions of array properties:
    IReadOnlyList<Byte> IReadOnlyUser.PasswordHash => this.PasswordHash;
    IReadOnlyList<Byte> IReadOnlyUser.PasswordSalt => this.PasswordSalt;
    }

    public static void DoReadOnlyStuffWithUser( IReadOnlyUser user )
    {
    ...
    }

    // This method still uses `User` instead of `IReadOnlyUser` because it mutates the instance.
    public static void WriteStuffToUser( User user )
    {
    ...
    }





    share|improve this answer















    The technique you're referring to is called "const-correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.



    Alternatively, there's a much simpler solution using interfaces: because C# (and I think the CLR too) does not support const-correctness (the closest we have is the readonly field modifier) the .NET base-class-library designers added "read-only interfaces" to common mutable types to allow a object (wheather mutable or immutable) to expose its functionality via an interface that only exposes immutable operations. Some examples include IReadOnlyList<T>, IReadOnlyCollection<T>, IReadOnlyDictionary<T> - while these are all enumerable types the technique is good for singular objects too.



    This design has the advantage of working in any language that supports interfaces but not const-correctness.




    1. For each type (class, struct, etc) in your project that needs to expose data without risk of being changed - or any immutable operations then create an immutable interface.

    2. Modify your consuming code to use these interfaces instead of the concrete type.


    Like so:



    Supposing we have a mutable class User and a consuming service:



    public class User
    {
    public String UserName { get; set; }

    public Byte PasswordHash { get; set; }
    public Byte PasswordSalt { get; set; }

    public Boolean ValidatePassword(String inputPassword)
    {
    Hash inputHash = Crypto.GetHash( inputPassword, this.PasswordSalt );
    return Crypto.CompareHashes( this.PasswordHash, inputHash );
    }

    public void ResetSalt()
    {
    this.PasswordSalt = Crypto.GetRandomBytes( 16 );
    }
    }

    public static void DoReadOnlyStuffWithUser( User user )
    {
    ...
    }

    public static void WriteStuffToUser( User user )
    {
    ...
    }


    Then make an immutable interface:



    public interface IReadOnlyUser
    {
    // Note that the interfaces' properties lack setters.
    String UserName { get; }
    IReadOnlyList<Byte> PasswordHash { get; }
    IReadOnlyList<Byte> PasswordSalt { get; }

    // ValidatePassword does not mutate state so it's exposed
    Boolean ValidatePassword(String inputPassword);

    // But ResetSalt is not exposed because it mutates instance state
    }


    Then modify your User class and consumers:



    public class User : IReadOnlyUser
    {
    // (same as before, except need to expose IReadOnlyList<Byte> versions of array properties:
    IReadOnlyList<Byte> IReadOnlyUser.PasswordHash => this.PasswordHash;
    IReadOnlyList<Byte> IReadOnlyUser.PasswordSalt => this.PasswordSalt;
    }

    public static void DoReadOnlyStuffWithUser( IReadOnlyUser user )
    {
    ...
    }

    // This method still uses `User` instead of `IReadOnlyUser` because it mutates the instance.
    public static void WriteStuffToUser( User user )
    {
    ...
    }






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 25 '18 at 2:10

























    answered Nov 25 '18 at 1:29









    DaiDai

    73.3k13118204




    73.3k13118204








    • 3





      Side note: interfaces alone will not protect from un-friendly caller as they can use reflection/cast/dynamic to call SetXxxx methods of the implementing class. If this is the case you need both - interfaces and proxy implementation that hides the actual class.

      – Alexei Levenkov
      Nov 25 '18 at 2:06






    • 3





      @AlexeiLevenkov That's no-different to using const_cast in C++ though. I don't think it's worth developing countermeasures to adversarial library consumers anyway, as this is about eliminating potential bugs, not security.

      – Dai
      Nov 25 '18 at 2:12













    • Indeed in case of friendly client interfaces are enough. It is unclear how much protection OP is looking for "be sure that it will not be modified by the client" can be read in many different ways.

      – Alexei Levenkov
      Nov 25 '18 at 2:48











    • @Alexei Levenkov My intent with this is as Dai said, more related to preventing potential bugs than security. Sorry for not being entirely clear. Good observation nonetheless.

      – Leonardo Raele
      Nov 25 '18 at 13:27














    • 3





      Side note: interfaces alone will not protect from un-friendly caller as they can use reflection/cast/dynamic to call SetXxxx methods of the implementing class. If this is the case you need both - interfaces and proxy implementation that hides the actual class.

      – Alexei Levenkov
      Nov 25 '18 at 2:06






    • 3





      @AlexeiLevenkov That's no-different to using const_cast in C++ though. I don't think it's worth developing countermeasures to adversarial library consumers anyway, as this is about eliminating potential bugs, not security.

      – Dai
      Nov 25 '18 at 2:12













    • Indeed in case of friendly client interfaces are enough. It is unclear how much protection OP is looking for "be sure that it will not be modified by the client" can be read in many different ways.

      – Alexei Levenkov
      Nov 25 '18 at 2:48











    • @Alexei Levenkov My intent with this is as Dai said, more related to preventing potential bugs than security. Sorry for not being entirely clear. Good observation nonetheless.

      – Leonardo Raele
      Nov 25 '18 at 13:27








    3




    3





    Side note: interfaces alone will not protect from un-friendly caller as they can use reflection/cast/dynamic to call SetXxxx methods of the implementing class. If this is the case you need both - interfaces and proxy implementation that hides the actual class.

    – Alexei Levenkov
    Nov 25 '18 at 2:06





    Side note: interfaces alone will not protect from un-friendly caller as they can use reflection/cast/dynamic to call SetXxxx methods of the implementing class. If this is the case you need both - interfaces and proxy implementation that hides the actual class.

    – Alexei Levenkov
    Nov 25 '18 at 2:06




    3




    3





    @AlexeiLevenkov That's no-different to using const_cast in C++ though. I don't think it's worth developing countermeasures to adversarial library consumers anyway, as this is about eliminating potential bugs, not security.

    – Dai
    Nov 25 '18 at 2:12







    @AlexeiLevenkov That's no-different to using const_cast in C++ though. I don't think it's worth developing countermeasures to adversarial library consumers anyway, as this is about eliminating potential bugs, not security.

    – Dai
    Nov 25 '18 at 2:12















    Indeed in case of friendly client interfaces are enough. It is unclear how much protection OP is looking for "be sure that it will not be modified by the client" can be read in many different ways.

    – Alexei Levenkov
    Nov 25 '18 at 2:48





    Indeed in case of friendly client interfaces are enough. It is unclear how much protection OP is looking for "be sure that it will not be modified by the client" can be read in many different ways.

    – Alexei Levenkov
    Nov 25 '18 at 2:48













    @Alexei Levenkov My intent with this is as Dai said, more related to preventing potential bugs than security. Sorry for not being entirely clear. Good observation nonetheless.

    – Leonardo Raele
    Nov 25 '18 at 13:27





    @Alexei Levenkov My intent with this is as Dai said, more related to preventing potential bugs than security. Sorry for not being entirely clear. Good observation nonetheless.

    – Leonardo Raele
    Nov 25 '18 at 13:27













    0














    So, these are the first two ideas I initially had, but don't quite solve the problem.



    Using Dynamic Objects:



    The first idea I had was creating a Dynamic Object that would intercept all member invokations and throw an error if the method being called isn't marked with a [Constant] custom attribute. This approach is problematic because a) We don't have the support of the compiler to check for errors in the code (i.e. method name typos) when dealing with dynamic objects, which might lead to a lot of runtime errors; and b) I intend to use this a lot, and searching for method names by name every time a method is called might have considerable performance impact.



    Using RealProxy:



    My second idea was using a RealProxy to wrap the real object and validate the methods being called, but this only works with objects that inherit from MarshalByRefObject.






    share|improve this answer




























      0














      So, these are the first two ideas I initially had, but don't quite solve the problem.



      Using Dynamic Objects:



      The first idea I had was creating a Dynamic Object that would intercept all member invokations and throw an error if the method being called isn't marked with a [Constant] custom attribute. This approach is problematic because a) We don't have the support of the compiler to check for errors in the code (i.e. method name typos) when dealing with dynamic objects, which might lead to a lot of runtime errors; and b) I intend to use this a lot, and searching for method names by name every time a method is called might have considerable performance impact.



      Using RealProxy:



      My second idea was using a RealProxy to wrap the real object and validate the methods being called, but this only works with objects that inherit from MarshalByRefObject.






      share|improve this answer


























        0












        0








        0







        So, these are the first two ideas I initially had, but don't quite solve the problem.



        Using Dynamic Objects:



        The first idea I had was creating a Dynamic Object that would intercept all member invokations and throw an error if the method being called isn't marked with a [Constant] custom attribute. This approach is problematic because a) We don't have the support of the compiler to check for errors in the code (i.e. method name typos) when dealing with dynamic objects, which might lead to a lot of runtime errors; and b) I intend to use this a lot, and searching for method names by name every time a method is called might have considerable performance impact.



        Using RealProxy:



        My second idea was using a RealProxy to wrap the real object and validate the methods being called, but this only works with objects that inherit from MarshalByRefObject.






        share|improve this answer













        So, these are the first two ideas I initially had, but don't quite solve the problem.



        Using Dynamic Objects:



        The first idea I had was creating a Dynamic Object that would intercept all member invokations and throw an error if the method being called isn't marked with a [Constant] custom attribute. This approach is problematic because a) We don't have the support of the compiler to check for errors in the code (i.e. method name typos) when dealing with dynamic objects, which might lead to a lot of runtime errors; and b) I intend to use this a lot, and searching for method names by name every time a method is called might have considerable performance impact.



        Using RealProxy:



        My second idea was using a RealProxy to wrap the real object and validate the methods being called, but this only works with objects that inherit from MarshalByRefObject.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 25 '18 at 1:18









        Leonardo RaeleLeonardo Raele

        5901923




        5901923






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53463876%2fwhat-is-the-best-approach-or-alternative-to-constant-references%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Costa Masnaga

            Fotorealismo

            Sidney Franklin