1

Let's say I have the following C# class:

class MyClass ()
{
    public readonly DataTable dt = new DataTable();
    ...
}

What's the meaning of readonly for reference types? I just implemented this code and the user is atill able to modify the datatable.

How can I prevent the user from writing or mutating my datatable (or any object in general)? I.e., just read access. Obviously using properties wouldn't help here.

sapito
  • 1,472
  • 3
  • 17
  • 26
  • 2
    here is where you can find the answer to your question [C# Find explanation of readonly](http://www.google.com) also how can users update / alter data returned in code behind unless you are allowing it.. perhaps you need to fix any code that does that or explain better what the heck it is your are really trying to achieve ... – MethodMan Dec 19 '14 at 19:48
  • I have already googled it and I don't understand how to achieve the result I am asking for. I just want users to have ONLY read access to this datatable, and other objects in general. – sapito Dec 19 '14 at 19:50
  • what do you mean.. you create an Instance of DataaTable object.. sooooo..... what do you do from there.. you have not shown what you are trying to achieve – MethodMan Dec 19 '14 at 19:51
  • Let's say something similar to C++ const methods. I think you don't understand my question anyway. I think I have explained well enough. – sapito Dec 19 '14 at 19:52

3 Answers3

4

Readonly means that you can not reassign the variable - e.g. later on you can not assign a new DataTable to dt.

As for making the object itself read-only - that entirely depends on the object itself. There is no global convention for making objects immutable.

I didn't see anything specific to achieve this with .NET's DataTable but some options would be to

  1. Ensure that the user doesn't have modify permissions in the database itself (most secure)
  2. Look for ReadOnly attributes on whatever grid/controls you are binding to it (also clear to the users then that this is read-only)
DamienG
  • 6,575
  • 27
  • 43
  • 3
    3. Return to the user a [copy](http://msdn.microsoft.com/en-us/library/system.data.datatable.copy(v=vs.110).aspx) of the class, however you must be careful of [Shallow Copies vs Deep Copies](http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy) as if your Data Table (or whatever other reference type you are trying to make "Read Only") holds reference types within it those could still be modified if it is a shallow copy) – Scott Chamberlain Dec 19 '14 at 19:53
  • While that works for objects that hold their own state it is unlikely that would work here as the DataTable will be sending updates to the database. – DamienG Dec 19 '14 at 19:54
  • The DataTable isn't connected to any database. In any case, it is a big one. It seems returning a `dt.Copy()` would be a costly solution. Doesn't C# have something like C++ const methods? I.e., the user is only allowed to call const methods on readonly variables/reference types. – sapito Dec 19 '14 at 19:55
  • @sapito no, C# does not have any such construct. If you want that feature you would need to use managed C++ (and it still would not work for DataTable as I don't think it has any const methods declared). – Scott Chamberlain Dec 19 '14 at 19:56
  • how dos the user know this.. sounds like you need to write the code that would not allow for such things or explain yourself better especially in regards to your statement about `The DataTable isn't connected to any database` – MethodMan Dec 19 '14 at 19:58
  • If the DataTable isn't connected to a database then why do you think they are mutating your database? – DamienG Dec 19 '14 at 20:01
  • @ScottChamberlain: ok, actually C# seems a bit flawed when it comes to const correctness. I understand that `readonly` here means that user cannot assign a new DataTable to dt. But what I was trying to achieve is "if the user tries to modify any cell of the DataTable the compiler will complain", which is quite straighforward in C++ using const methods. – sapito Dec 19 '14 at 20:02
  • @DamienG: no databases here. The DataTable is just used for writing big Excel files. I just wanted to prevent users from mutating the DataTable in some cases. It seems only solution is returning a copy in these cases. Actually when I say "users" I meant "users of a library I am writing". – sapito Dec 19 '14 at 20:05
  • 1
    Does your client need the exact same interface as DataTable? Another solution is to put a wrapper around the datatable that does not allow writes and return that instead. I don't know of any off the top of my head, but depending upon your client's requirement it may not be that hard to roll your own. – Martin Brown Dec 19 '14 at 20:11
  • No, but I guess they are used to DataTable interfaces. The problem here is that some users may feel tempted to write some cells when doing some data processing. I may consider returning a copy even if it is a costly operation. I intend to make the code as safe as possible. – sapito Dec 19 '14 at 20:15
  • The problem with making a copy is that users will believe they are making changes as it will appear that way on the UI... but then they will be lost. Your best bet really is to go down a route that disables or otherwise makes it clear to the user that no data is changing. – DamienG Dec 19 '14 at 21:17
2

you can make a class like this:

class MyClass
{
    private DataTable dt = new DataTable();
    public MyClass()
    {
       //initialize your table
    }
    //this is an indexer property which make you able to index any object of this class
    public object this[int row,int column] 
    {
        get
        {
            return dt.Rows[row][column];
        }
    }

    /*this won't work (you won't need it anyway)
     * public object this[int row][int col]*/
    //in case you need to access by the column name
    public object this[int row,string columnName]
    {
        get 
        {
            return dt.Rows[row][columnName];
        }
    }



}

and use it like this example here:

 //in the Main method
 MyClass e = new MyClass();
 Console.WriteLine(e[0, 0]);//I added just one entry in the table

ofcourse if you wrote this statement

e[0,0]=2;

it will produce an error similar to this: Property or indexer MyNameSpace.MyClass.this[int,int] cannot be assigned to --it is read only.

niceman
  • 2,653
  • 29
  • 57
  • Thanks. I may consider implementing this at a later stage. Right now most users of the library expect a DataTable interface. Even if it's not necessary. – sapito Dec 19 '14 at 20:28
  • @sapito put some effort on your questions so they don't get downvoted. – niceman Dec 19 '14 at 20:34
0

readonly means that the Datatable will be a runtime constant as opposed to a compile time constant

  • But it's the *reference* that's "constant", you can still modify the *contents* of the datatable - which is what the OP wants to prevent. – Hans Kesting Dec 20 '14 at 09:31