How can I search for a specific struct value? Mayb

2019-05-29 19:47发布

问题:

I'm trying to find a struct I created earlier that has a specific value. Once I found it, I want to set variables on that struct. I don't know how to do this. Is there a better way of doing this? Maybe classes? Or should structs work?

For example, my struct:

public struct MyTest
{
    public string device;
    public string status;
    public string revision;
    public string number;
    public string ledmo;        
}

My Test Code:

MyTest thisTest=new MyTest();
thisTest.device=blah;
thisTest.number=blah2;

MyTest thisTest2=new MyTest();
thisTest2.device=blah5;
thisTest2.number=blah6;

//Another Part in my code.
//Need to find the MyTest Structure that 'device' variable = the string 'blah'
var Foundit=MyTest.find(device==blah);
Foundit.revision=blah9999;

回答1:

I'd use a class, because Mutable structs are evil

Basically, because every struct is copied, even if you do find the right struct, you'll only ever change one copy. Lets say MyTest.find finds thisTest2 what happens is this

var Foundit = MyTest.Find(device==blah); 
// The line above has made a copy of thisTest2, that copy is in FoundIt

Foundit.revision = "blah9999";
// You've changed revision in the copy of thisTest2, 
// therefore the contents of thisTest2 remain unchanged

To do this with a class you'll need to keep every instance of the class you create in a list or other data structure, so you know you can look it up.

If you do this you also need to tell the list when you're finished with each object, otherwise they'll hang around forever and never get garbage collected.

Before I go any further, are you sure this is the best way to solve this problem?

Anyway, say your class is MyData, you can put a static factory method on this called Create, which will put each new MyData object into a list.

public class MyData
{
    private static List<MyData> allMyDatas = new List<MyData>();
    public static IEnumerable<MyData> AllInstances
    {
        get {return allMyDatas;}
    }

    public string Device {get; set;}
    public string Status {get; set;}
    public string Revision {get; set;}
    public string Number {get; set;}
    public string Ledmo {get; set;}

    private MyData() // Private ctor ensures only a member 
    {                // function can create a new MyData
    }
    public static MyData Create()
    {
        var newData = new MyData();
        allMyDatas.Add(newData);
        return newData;
    }

    public static void Delete(MyData itemToRemove)
    {
        allMyDatas.Remove(itemToRemove);
    }
}

Everywhere you use a MyData you'll need to Delete it when you're finished with it.

Your code becomes

var thisTest = MyData.Create();
thisTest.Device = "blah";
thisTest.Number = "blah2";

var  thisTest2 = MyData.Create();
thisTest2.Device = "blah5";
thisTest2.Number = "blah6";

//Another Part in my code.
//Need to find the MyData Structure that 'device' variable = the string 'blah'
var Foundit = MyData.AllInstances.FirstOrDefault(md => md.Device == "blah");
if(Foundit != null)
    Foundit.Revision = "blah9999";    

Changing FoundIt now also changes thisTest

P.S.: It's important that nothing outside MyData can new an instance of MyData. If it could, then there would be an instance of MyData that you couldn't find in AllInstances. Declaring the constructor private means a compiler error will be generated if code outside MyData tries something like var someData = new MyData



回答2:

To be able to find instances of an object created earlier, these instances need to be saved somewhere.
One solution would be to put them into a list and later search that list:

var list = new List<MyTest>();

MyTest thisTest=new MyTest();
thisTest.device=blah;
thisTest.number=blah2;
list.Add(thisTest);

MyTest thisTest2=new MyTest();
thisTest2.device=blah5;
thisTest2.number=blah6;
list.Add(thisTest2);

Now you can search using LINQ:

var foundItems = list.Where(x => x.device == "blah");
foreach(var foundItem in foundItems)
{
    foundItem.revision = "blah9999";
}

Please note:
This only works when you use classes instead of structs as Binary Worrier points out in his comment.



回答3:

In this case a class would work better because of the dynamic string size and the fact that there are so many strings.

With your test code, you should be storing a List<MyTest> somewhere in that class and adding thisTest and thisTest2 to the list. You can later retrieve specific values (or all the values of a certain device) with the FindAll or similar methods.

List<MyTest> list = new List<MyTest>();
//add MyTests here...

var foundIt = list.FindAll(x => x.device == "blah");


回答4:

You can use lists and Linq for that.

var test = new List<MyTest>();
//Add some items
var foundIt = test.SingleOrDefault(test => test.device == "abc");//Maximum one
if(foundIt != null)//Use a class for MyTest.
   foundIt.device = "123"