This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
I have recently updated by Lightspeed for an existing project to the latest version. But since I have, I have many new errors being highlighted by Resharper. Resharper is giving me the option ignore the warnings, but before I do ignore them I owuld like to find why I am suddenly getting these. The code used is as follows. We have a generic methd to save enteties. public static Boolean SaveEntity<T>(ref T entity) where T : Entity uow.Attach(entity);
Then within forms or classes we defined local variables. Update them, then save the changes. var car = new Car(); car.BeginEdit(); car.Color = @"Red"; car.EndEdit(); var result = ContextData.SaveEntity<Car>(ref car);
I have been using this model of code for about two years, and as far as I know, never had a problem. But as I said, now I get all these warning. Can anyone advise, should I worry about these warnings, or just ignore them? Thanks
|
|
|
There is no problem with your code per se, but there is a tweak you could and should make. It's not clear to me whether that CS0197 is a C# compiler warning or a Resharper warning. There is a C# compiler warning CS0197, but it applies to passing a *field* of a MarshalByRefObject as a ref or out parameter. You are quoting a different error message, and in the fragment you post, you are not passing a field of car, and car is not a MarshalByRefObject. So I am assuming this is some Resharper warning where they have helpfully decided to reuse C# compiler error numbers for different errors. Assuming this is the case, the Resharper warning appears to be spurious. You are not passing a MarshalByRefObject as a ref or out parameter. Possibly the Resharper folks have confused the concept of a reference type (which an Entity is) with a marshal-by-reference type (which an Entity isn't). The former is safe to pass as a ref or out parameter, though it's unusual unless it's an immutable reference type like String. So here comes the tweak. You only pass an object as ref if you want to be able to replace it with a different object. You don't do this in your SaveEntity method. In fact, it would be very confusing if SaveEntity replaced the entity being saved with a different entity! So you should remove the ref modifier from the entity argument anyway. This will make calling code easier to read, and prevent a future maintainer of SaveEntity accidentally overwriting the entity argument with surprising results for the rest of the program. |
|
|
Hi Ivan, Thanks for the prompt reply. To be clear, it is ReSharper that is highlighting the code and giving the warning. So, based on your feedback it seems I can safely ignore this message. To be honest I sort of thought like that anyway, but it was good to get your opinion also. With regards to the tweak, the reason I pass a ref, is that way, after the save operation, I still have the same car for further processing if required, but the changes have been saved and the EntityState and LockVersion updated based on the save. If I don't use a ref, the "copy" of car that I send for saving will be saved, but the copy of car in my calling code will still be the unsaved version, so if I was to change it again, then try to save it again, I would get a concurrency violation. Hope this makes sense?
Best regards
|
|
|
You're right that the ref keyword is required if you want the method you're calling to modify a struct. However, it is NOT required for the method to modify a class. Entity is a class, so a called method can modify an Entity and the calling method will see the changes. This is because with a class, what gets passed is not a copy of the car, but a reference to the car. The Car object itself is out there in memory somewhere, and the calling method has a reference to it. When the calling method calls SaveEntity, SaveEntity does get a "copy" of the reference -- but what has been duplicated is the reference, not the Car. The duplicate of the reference still points to the same Car out in memory! (I hope this makes sense. It would be a lot easier to explain if our forums supported box-and-arrow diagrams. *grin*) So when SaveEntity changes the Car through its reference, the calling code sees the changes through its reference, because both references are to the same Car. You only need to use ref with class types if your method wants to be able to change the reference to point to a different Car. This isn't anything special to LightSpeed by the way -- it's just the way reference and value types (classes and structs) work in .NET, combined with Entity being a class rather than a struct. Of course, the ref modifier isn't doing any harm at the moment, except for the spurious warning, so don't get the impression I'm badgering you to change code that's working fine! Just mentioned it to save you using the ref modifier on future methods you write. |
|
|
Hi Ivan, Thanks for the lesson. ;-) Seriously though, greatly appreciated. Best regards |
|