|
This is complicated in many many levels
First off, if you want a read-only getter, and the list you return is small, then yeah, a copy would partially work:
public static List<SocketStructure> GetHostAddressesList() {
lock(m_locker) return m_HostAddress.ToList();
}
However, if SocketStructure is a class, you're still not completely safe.
Because you will have a copy of the list, but the elements themselves still point to your internal list - and they can still change as you access them.
What you want to return is a copy of the list (as shown above), and:
1. either have SocketStructure immutable
2. or make SocketStructure thread-safe as well.
3. make SocketStructure a struct (in that case each element in the returned list will be a copy of the original element)
Best,
John
|
|
|
|
|
Something like this maybe?
public static SocketStructure[] GetHostAddressesList() {
lock(m_locker)
{
List<SocketStructure>tmp = new List<SocketStructure>tmp();
for(int i = 0; i<m_HostAddress.Count(); i++)
{
SocketStructure s = new SocketStructure();
s.IP = m_HostAddress[i].IP;
s.port = m_HostAddress[i].port;
tmp.Add(s);
}
return tmp.ToList();
}
}
|
|
|
|
|
Almost Note that string is immutable, so you're fine there.
public static List<SocketStructure> GetHostAddressesList() {
lock(m_locker)
{
List<SocketStructure>tmp = new List<SocketStructure>();
for(int i = 0; i<m_HostAddress.Count(); i++)
{
SocketStructure s = new SocketStructure();
s.IP = m_HostAddress[i].IP;
s.port = m_HostAddress[i].port;
tmp.Add(s);
}
return tmp;
}
}
At the last line, you don't need to use .ToList(), since you've already created a new list.
Best,
John
|
|
|
|
|
Ok, so you recommend I use this one? Btw tmp isn't array type above
|
|
|
|
|
Yes, I do. About array - yes you're right. Just modified it now.
|
|
|
|
|
So when I am returning value types - it is fine? (from the point of view of multithreading). And assuming ALL my getters (both for value and reference types) have locks.
But if I return reference type I better make a deep copy, that is better practice you say right?
|
|
|
|
|
You nailed it
Best,
John
|
|
|
|
|
Thanks - I hope we understood each other
PS. (Same applies for strings I guess as it does with ints, since string are immutable)
PPS Just started thinking indeed returning reference to object even if you have locks inside getters is rather tricky - because some other thread might change contents of the reference type, and if you are left with the reference which you retrieved above you will see different results depending how other thread modifies it
|
|
|
|
|
Member 12061600 wrote: PS. (Same applies for strings I guess as it does with ints, since string are immutable)
Yes
Member 12061600 wrote: PPS Just started thinking indeed returning reference to object even if you have locks inside getters is rather tricky - because some other thread might change contents of the reference type, and if you are left with the reference which you retrieved above you will see different results depending how other thread modifies it
Yes, it's very tricky indeed. So I would suggest you go with the easy solution for now (immutable objects or structs)
Best,
John
-- LogWizard - Meet the Log Viewer that makes monitoring log files a joy!
|
|
|
|
|
Member 12061600 wrote: So when I am returning value types - it is fine?
Yes
Member 12061600 wrote: But if I return reference type I better make a deep copy, that is better practice you say right?
It all depends on what you're trying to achieve, but if you're not sure about it, it's safe to assume "yes". But as said in the other answer, I suggest you go for immutable objects or structs.
Best,
John
-- LogWizard - Meet the Log Viewer that makes monitoring log files a joy!
|
|
|
|
|
I already went with deep copy approach I showed you above (the code). So I will leave it like that?
Because I have classes instead of structs and they aren't immutable.
|
|
|
|
|
It's up to you. You can also create a struct used just for you clients, something like:
struct socket {
string ip;
int port;
}
and return a list of that.
Best,
John
-- LogWizard - Meet the Log Viewer that makes monitoring log fies a joy!
|
|
|
|
|
Thanks but if there is no difference, I will leave it with deep copy, since I already implemented that.
|
|
|
|
|
1. Sounds good
2. It's pretty much another way to deep copy. But also, if you create a new struct, you can decide what your client has access to - at this point, it has access to all members of SocketStructure. With a struct, you would decide exactly what your client sees.
It the case of a simple structure (such as your SocketStructure), having a struct would probably be overkill, but for more complex classes, it might be a solution.
Best,
John
|
|
|
|
|
2. It's pretty much another way to deep copy. But also, if you create a new struct, you can decide what your client has access to - at this point, it has access to all members of SocketStructure. With a struct, you would decide exactly what your client sees.
Not sure I understood that - maybe because I am not very experienced with .NET yet. But if from thread safety point of view there is no difference whether I do a deep copy like I showed in my code, or return copied structs, I will stick to my approach then ...
It is ok if client has access to all members ...
|
|
|
|
|
Member 12061600 wrote: I will stick to my approach then ...
Sounds good
Best,
John
|
|
|
|
|
|
You're welcome!
Best,
John
-- LogWizard Meet the Log Viewer that makes monitoring log files a joy!
|
|
|
|
|
Because you will have a copy of the list, but the elements themselves still point to your internal list - and they can still change as you access them.
Then every time I want to access the hostAddresses list I should use a getter instead of storing it in a a tmp variable like I have above, isn't it? because modifying (adding/removing items from) the hostList is protected with a lock inside say Add function, and if someone modifies it between two executions of getters, that is fine, I can't control that, but if I used tmp variable - then each time it would show old values
|
|
|
|
|
If SocketStructure is a struct or an immutable class , then you might want to consider using the immutable collections[^] from NuGet[^].
That way, any modifications to the collection will create a new collection instance, and replace the existing field. Any threads which have already retrieved a version of the collection will not see the changes unless they retrieve it again.
The immutable collections were designed to minimize the cost of creating a new version of the collection for every change.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I want to write a class named as "Fingerprints" that upload, update and delete the fingerprints of source codes or other format files in desktop application of c# language.
|
|
|
|
|
thats good - whats your specific problem ? since you dont show any code, we cant really help you with it
|
|
|
|
|
I suggested in my response to your original question that you need to add some proper details to your question. For example, what do you mean by fingerprints of source codes or other format files? And where do you plan to 'upload' these files or fingerprints to?
|
|
|
|
|
I assume that what you are looking to do is to track the unique identities of files so you are wanting to look at things like the file path, the size of the file and a hash of the file contents - at a high level, this is the fingerprint of the file. Then you want to save this information somewhere, so you want to perform the CRUD operations on this information. Is this correct?
|
|
|
|
|
yeah you're true this is small part of my project
my actual project is develop a system for plagiarism detection
|
|
|
|