473,401 Members | 2,125 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,401 software developers and data experts.

Using property to reference Struct data

I don't understand why I cannot use a property to modify data within a
struct. Can someone tell me why I get the error "Cannot modify the return
value of "myData.TheData" because it is not a variable.

Here is what breaks.

struct Data
{
public Data(){}
private int someData;
public int TheData
{
get { return someData; }
set { someData = value; }
}
}

class Sample
{
Data myData = new Data();

void AMethod()
{
myData.TheData = 7;
}
}

If I don't use the property "TheData" and instead make "int someData" public
I can reference myData.someData = 7 and it will work just fine. Why can't a
property be used?

--
-----------
Thanks,
Steve
Feb 7 '06 #1
14 3256
The property construct is fine.

I'm wondering why you declared a default constructor for a struct,
though, since C# doesn't allow them. Try removing the constructor and
see if it works.

Feb 7 '06 #2
This isn't the code that gave you that warning. This code fails to
compile with the error, "Structs cannot have parameterless
constructor." Please post the exact code that gave you the error.

Feb 7 '06 #3
Adding the constructor was my mistake. I don't have it in the actual code.

A MS help comment says:

Error Message
Cannot modify the return value of 'expression' because it is not a variable

An attempt was made to modify a value type that was the result of an
intermediate expression. Because the value is not persisted, the value will
be unchanged.

To resolve this error, store the result of the expression in an intermediate
value, or use a reference type for the intermediate expression.
I therefore created a temp value and assigned my structure to it. The only
thing is that when updating the temp reference it didn't update my structure.

Data tmp = myData;
tmp.TheData = 7;

This assigned 7 to TheData in the tmp value, but it didn't update the myData
"data". I can't figure out way.

myData is part of a static global structure. Could the static nature have
anything to do with it?
--
-----------
Thanks,
Steve
"dotnetchic" wrote:
The property construct is fine.

I'm wondering why you declared a default constructor for a struct,
though, since C# doesn't allow them. Try removing the constructor and
see if it works.

Feb 7 '06 #4
I copied your code in to a VS2003 project, removed the spurious
constructor, and it compiles with no warnings or errors.

Please post the exact code that caused this compiler error. I suspect I
know what's going on, but I can't say until I see the real code.

Feb 7 '06 #5
Here is my code, I trimmed out the stuff that wasn't necessary.

Create a project called TestSamples with a form that does nothing for now.
Simple insert this code and it will compile with the error I indicated. If
you change "public struct TimeDelayEventData" to "public class
TimeDelayEventData" then it works just fine.

This code is my "GlobalData class"

using System;
using System.Collections;

namespace TestSamples
{
/// <summary>
/// Summary description for Class1.
/// </summary>
internal class GlobalData
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit.
static GlobalData() {}
/// <summary>
/// Default constructor
/// </summary>
private GlobalData()
{
// Set up the global data structures
this.timeDelayData = new TimeDelayEventData();

// Set up event handlers for the time delay events
this.timeDelayRequestor = new TimeDelayRequestEvents();
this.timeDelayListener = new TimeDelayFullfillEvents();
this.timeDelayListener.AddEvent(this.timeDelayRequ estor);
}

/// <summary>
/// Create a static instance of this class.
/// </summary>
static readonly GlobalData instance = new GlobalData();
/// <summary>
/// References the data regarding the time delays for the testing
/// </summary>
private TimeDelayEventData timeDelayData;
/// <summary>
/// Reference to the event handler to fulfill the event of passing
time delay data to the global data structure
/// </summary>
private TimeDelayFullfillEvents timeDelayListener;
/// <summary>
/// Reference to the event handler to request time delay events
/// </summary>
private TimeDelayRequestEvents timeDelayRequestor;

/// <summary>
/// Get a reference to this instance of this class.
/// </summary>
public static GlobalData Instance
{
get { return GlobalData.instance; }
}

/// <summary>
/// Get a reference to the time delay data.
/// </summary>
public TimeDelayEventData MyTimeDelayData
{
get
{
return this.timeDelayData;
}
}

/// <summary>
/// Get a reference to the time delay requestor
/// </summary>
public TimeDelayRequestEvents MyTimeDelayRequestor
{
get
{
return this.timeDelayRequestor;
}
}
}
}
Here is my TimeDelayEventData struct...

using System;
using System.Collections.Generic;
using System.Text;

namespace TestSamples
{
public struct TimeDelayEventData
{
/// <summary>
/// Ignore the date when asked to run the test
/// </summary>
private bool ignoreDate;
/// <summary>
/// This enum identifies the data that is to be updated
/// </summary>
private TimeDelayIdentifiers timeDelayIdentifier;

/// <summary>
/// Get or set the flag indicating that the date should be ignored
when asked to run the test
/// </summary>
public bool IgnoreDate
{
get
{
return ignoreDate;
}
set
{
ignoreDate = value;
}
}
/// <summary>
/// Get or set the identifier that identifies the data to be updated
in the event
/// </summary>
public TimeDelayIdentifiers Identifier
{
get
{
return timeDelayIdentifier;
}
set
{
timeDelayIdentifier = value;
}
}
}
}

Here is my event handler classes...

using System;
using System.Collections.Generic;
using System.Text;

namespace TestSamples
{
/// <param name="hourData">This structure identifies and contains the
data to be sent to the event</param>
public delegate void TimeDelayEventHandler(TimeDelayEventData data);

public class TimeDelayRequestEvents
{
/// <summary>
/// This event requests an update to the hour data.
/// </summary>
public event TestSamples.TimeDelayEventHandler
timeDelayUpdateRequestEvent;

/// <summary>
/// Default constructor
/// </summary>
public TimeDelayRequestEvents()
{
}

/// <summary>
/// Issue the request to update the hour data.
/// </summary>
/// <param name="obj">Time Delay data to be updated when an event
occurs</param>
private void RequestUpdateEvent(TimeDelayEventData obj)
{
if (timeDelayUpdateRequestEvent != null)
timeDelayUpdateRequestEvent(obj);
}

/// <summary>
/// Make the request to update the data being passed for time delay
information.
/// </summary>
/// <param name="obj">Time Delay data to be udpated when an event
occurs</param>
public void OnUpdate(TimeDelayEventData obj)
{
RequestUpdateEvent(obj);
}
}

/// <summary>
/// This class handles all fullfillments requests for updating the
global data representing the time delay data.
/// </summary>
public class TimeDelayFullfillEvents
{
/// <summary>
/// References the request to handle a time delay event
/// </summary>
private TimeDelayRequestEvents requestEvent = null;
/// <summary>
/// Default constructor
/// </summary>
public TimeDelayFullfillEvents()
{
}

/// <summary>
/// Remove any previous event instance.
/// </summary>
protected void RemoveEvent()
{
if (this.requestEvent != null)
this.requestEvent.timeDelayUpdateRequestEvent -= new
TimeDelayEventHandler(this.UpdateTimeDelayData);
}

/// <summary>
/// Update the data for the time delay information
/// </summary>
private void UpdateTimeDelayData(TimeDelayEventData data)
{
switch (data.Identifier)
{
case TimeDelayIdentifiers.IgnoreDate:
GlobalData.Instance.MyTimeDelayData.IgnoreDate =
data.IgnoreDate;
break;
}
}

/// <summary>
/// Add the event handler for the time delay events
/// </summary>
/// <param name="request">Requesting event to update the time delay
data</param>
public void AddEvent(TimeDelayRequestEvents request)
{
// Remove any instances of an old request.
this.RemoveEvent();

// Create the new handler.
this.requestEvent = request;
this.requestEvent.timeDelayUpdateRequestEvent +=new
TimeDelayEventHandler(this.UpdateTimeDelayData);
}
}
}
Here is my TimeDelayIdentifiers...

using System;
using System.Collections.Generic;
using System.Text;

namespace TestSamples
{
/// <summary>
/// This enum is used to identify which data in the event is to be updated
/// </summary>
public enum TimeDelayIdentifiers
{
/// <summary>
/// Indicates the data is in the ignoreDate field
/// </summary>
IgnoreDate = 1,
}
}

--
-----------
Thanks,
Steve
"Bruce Wood" wrote:
I copied your code in to a VS2003 project, removed the spurious
constructor, and it compiles with no warnings or errors.

Please post the exact code that caused this compiler error. I suspect I
know what's going on, but I can't say until I see the real code.

Feb 7 '06 #6
I presume that you have a class that has, as one of its members, a
variable of a structure type and that you are trying to do something
like this:

ClassVariable.Structure.StructureProperty = 1;

You are getting the error because when you call ClassVariable.Structure
you are getting a *copy* of the structure and not a reference to the
actual structure. So any changes you make to *copy* will not be copied
to the structure in the class.

You need to do something like this:

//Get the copy of the structure and save in a variable
MyStruct tmp = ClassVariable.Structure;

//Modify the copy
tmp.StructureProperty = 1;

//Replace the structure in the class instance with the copy.
ClassVariable.Structure = tmp;

Or, instead of a structure, use a class then you wont have to create a
tmp copy since you will be working with references.

Feb 7 '06 #7
And the line that causes the compiler error is:

GlobalData.Instance.MyTimeDelayData.IgnoreDate = data.IgnoreDate;

in class TimeDelayFullfillEvents. Right?

Remember that structs have _value semantics_. That means that when you
say: GlobalData.Instance.MyTimeDelayData, you are getting a _copy_ of
the TimeDelayData within the GlobalData object, not a _reference_ to
the TimeDelayData.

So, when you say MyTimeDelayData.IgnoreDate = ... what you're saying
is, "Return me a copy of the TimeDelayData from the GlobalData object,
then make a change to that copy, then throw it away." Throw it away
because you don't store the copy anywhere, so the compiler chucks it.

Mutable structs are strange beasts and tricky to work with. Unless
you're going to be creating and destroying millions (and I do mean
_millions_) of these things, you're better off making it a class, not a
struct. Then it will act in a more reasonable manner. The other
possibility is to make it immutable (no sets in any of your struct's
properties), which forces you to create a "new" one and assign it to
the property, rather than trying to set _its_ properties.

Feb 7 '06 #8
With your explanation and Bruce's this has clarified for me my mistake.
Thanks to you both.
--
-----------
Thanks,
Steve
"Chris Dunaway" wrote:
I presume that you have a class that has, as one of its members, a
variable of a structure type and that you are trying to do something
like this:

ClassVariable.Structure.StructureProperty = 1;

You are getting the error because when you call ClassVariable.Structure
you are getting a *copy* of the structure and not a reference to the
actual structure. So any changes you make to *copy* will not be copied
to the structure in the class.

You need to do something like this:

//Get the copy of the structure and save in a variable
MyStruct tmp = ClassVariable.Structure;

//Modify the copy
tmp.StructureProperty = 1;

//Replace the structure in the class instance with the copy.
ClassVariable.Structure = tmp;

Or, instead of a structure, use a class then you wont have to create a
tmp copy since you will be working with references.

Feb 7 '06 #9
This explanation has clarified for me my mistake. Thank you for you time.
I'll use it as a class.

Would you mind looking at my post "An Event Listener" posted today? Maybe
you can help me there as well.

--
-----------
Thanks,
Steve
"Bruce Wood" wrote:
And the line that causes the compiler error is:

GlobalData.Instance.MyTimeDelayData.IgnoreDate = data.IgnoreDate;

in class TimeDelayFullfillEvents. Right?

Remember that structs have _value semantics_. That means that when you
say: GlobalData.Instance.MyTimeDelayData, you are getting a _copy_ of
the TimeDelayData within the GlobalData object, not a _reference_ to
the TimeDelayData.

So, when you say MyTimeDelayData.IgnoreDate = ... what you're saying
is, "Return me a copy of the TimeDelayData from the GlobalData object,
then make a change to that copy, then throw it away." Throw it away
because you don't store the copy anywhere, so the compiler chucks it.

Mutable structs are strange beasts and tricky to work with. Unless
you're going to be creating and destroying millions (and I do mean
_millions_) of these things, you're better off making it a class, not a
struct. Then it will act in a more reasonable manner. The other
possibility is to make it immutable (no sets in any of your struct's
properties), which forces you to create a "new" one and assign it to
the property, rather than trying to set _its_ properties.

Feb 7 '06 #10
Hi Steve,

Thanks for your post.

I modified your code snippet into the following runnable code, however, it
does not get any runtime error on my side:

struct Data
{
private int someData;
public int TheData
{
get { return someData; }
set { someData = value; }
}
}

class Sample
{
public static void AMethod()
{
Data myData = new Data();
myData.TheData = 7;
}
}

static void Main()
{
Sample.AMethod();
}

Can you show me some more information to help us reproduce this problem?

I look forward to hearing from you. Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Feb 8 '06 #11
Steve Teeples <St****@newsgroups.nospam> wrote:
Adding the constructor was my mistake. I don't have it in the actual code.
It's really, really important that you post *actual* code which you've
tried to compile. If you take out the extra constructor, the code
you've posted works fine.
A MS help comment says:

Error Message
Cannot modify the return value of 'expression' because it is not a variable

An attempt was made to modify a value type that was the result of an
intermediate expression. Because the value is not persisted, the value will
be unchanged.
Right - and that *doesn't* happen in the test code you showed.
To resolve this error, store the result of the expression in an intermediate
value, or use a reference type for the intermediate expression.

I therefore created a temp value and assigned my structure to it. The only
thing is that when updating the temp reference it didn't update my structure.


No, it wouldn't - because that's not how value types work. When you've
fetched the value, that's created a copy of it. Modifying that value
doesn't modify the value which was originally copied.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Feb 8 '06 #12
Steve Teeples <St****@newsgroups.nospam> wrote:
Here is my code, I trimmed out the stuff that wasn't necessary.


With respect, you didn't really. This is just for future reference,
really. It's worth being able to come up with a "short but complete"
program that demonstrates a problem. You can do this either by keeping
on removing code from something that fails, or you can add code to
something that works.

In this case, you could have removed all the event stuff without
affecting the problem you were having. Here's an example:

using System;

class GlobalData
{
private GlobalData()
{
this.timeDelayData = new TimeDelayEventData();
}

static readonly GlobalData instance = new GlobalData();

private TimeDelayEventData timeDelayData;

public static GlobalData Instance
{
get { return GlobalData.instance; }
}

public TimeDelayEventData MyTimeDelayData
{
get
{
return this.timeDelayData;
}
}
}

public struct TimeDelayEventData
{
private bool ignoreDate;

public bool IgnoreDate
{
get
{
return ignoreDate;
}
set
{
ignoreDate = value;
}
}
}

class Test
{
static void Main()
{
GlobalData.Instance.MyTimeDelayData.IgnoreDate = false;
}
}

Now, you can go further than this, because you don't really need the
singleton to be a singleton:

public struct TimeDelayEventData
{
private bool ignoreDate;

public bool IgnoreDate
{
get
{
return ignoreDate;
}
set
{
ignoreDate = value;
}
}
}

class Test
{
private TimeDelayEventData timeDelayData =new TimeDelayEventData();

public TimeDelayEventData MyTimeDelayData
{
get
{
return this.timeDelayData;
}
}

static void Main()
{
Test t = new Test();
t.MyTimeDelayData.IgnoreDate = false;
}
}
Now *that's* an example without any unnecessary stuff. Instead of about
250 lines of code, it's 36!

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Feb 8 '06 #13
Jon,

I cannot believe that you took the time to do that. <grin>

Feb 8 '06 #14
Bruce Wood <br*******@canada.com> wrote:
I cannot believe that you took the time to do that. <grin>


I figure that if the message hits home, it could easily save me that
much time - maybe more - the next time, when I might not have the spare
time to do it :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Feb 8 '06 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: Grasshopper | last post by:
Hi, I am automating Access reports to PDF using PDF Writer 6.0. I've created a DTS package to run the reports and schedule a job to run this DTS package. If I PC Anywhere into the server on...
9
by: Guy | last post by:
I have extended the datetimepicker control to incorporate a ReadOnly property. I have used the new keyword to implement my own version of the value property, so that if readonly == true then it...
7
by: _ed_ | last post by:
I'd like to build a class or struct composed of pointers to variables. Does this require dropping into an 'unsafe' block, or is there a trick? .... int value1 = 1234; bool value2 = false;...
11
by: Nemanja Trifunovic | last post by:
A question for C# language experts: If I have a struct that implements IDisposable: struct C : IDisposable { public int clan; public void Dispose() { Console.WriteLine("Disposing");
0
by: Lokkju | last post by:
I am pretty much lost here - I am trying to create a managed c++ wrapper for this dll, so that I can use it from c#/vb.net, however, it does not conform to any standard style of coding I have seen....
6
by: JSheble | last post by:
Are there any reasons why I shouldn't or couldn't use a structure as a property in a class? Specifically since structures are value types and objects are reference types? I have a Shipping...
9
by: Bill Grigg | last post by:
All, Can anyone supply an example or reference to an example of using reflection to determine the data types and array lengths contained in a nested stucture in C#? Actually, it is a structure...
53
by: Hexman | last post by:
Hello All, I'd like your comments on the code below. The sub does exactly what I want it to do but I don't feel that it is solid as all. It seems like I'm using some VB6 code, .Net2003 code,...
45
by: Zytan | last post by:
This returns the following error: "Cannot modify the return value of 'System.Collections.Generic.List<MyStruct>.this' because it is not a variable" and I have no idea why! Do lists return copies...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.