zmiana pola wyszukanego elementu listy

0

Witam

Mam takie coś:

modbusreg.listregs.ElementAt(index)

i to zwraca mi element o danym indeksie z listy. Chciałbym dobrać się w ten lub inny sposób do publicznego pola tego elementu i np.go zmienić.
Próbowałem tak:

modbusreg.listregs.ElementAt(index).value = 5;

nie działa (błąd: cannot modify return value because it is not a variable), próbowałem też tak:

((ModbusReg.UserReg)(modbusreg.listregs.ElementAt(index))).value = 5;

też nie działa (błąd : cannot modify the result of an unboxing conversion), pytanie jak to zrobić ?

0

powinno dzialac bez problemow

http://stackoverflow.com/questions/19280986/best-way-to-update-an-element-in-a-generic-list

pokaz wiecej kodu (definicje klasy ktora jest w tej liscie i ktore pole chcesz zmienic)

0

Zrobiłem teraz tak:

var p = modbusreg.listregs.ElementAt(index);
p.value = 5;

błędów brak ale oczekiwanych efektów także.
Podejrzewam że ten cały elementat zwraca kopię tego obiektu.

Pokazuję więcej kodu:

    public class ModbusDrv
    {
        private ModbusReg modbusreg;

        private void AnalyzeFrame()
        {
            if (index < modbusreg.listregs.Count)
            {
                ....
                var p = modbusreg.listregs.ElementAt(index);
                p.value = 5;
               ...

               if (++index >= modbusreg.listregs.Count)
               {
                    index = 0;
               }
               ....
          }
       ...
      }
        ...
}

public class ModbusReg
    {
        public struct UserReg
        {
            public byte slave_address;
            public string name;
            public UInt16 address;
            public bool rw;
            public UInt16 value;
        }

        public List<UserReg> listregs;

        public ModbusReg()
        {
            listregs = new List<UserReg>();
        }
        ....
    }
0

Dodam tylko że to pytanie sprowadza się w zasadzie do tego :
Jak zmienić pole elementu listy o zadanym indeksie... ?

0

Metoda ElementAt() zwraca element listy, nie kopie. Obstawiam, że to raczej ty gdzieś podmieniasz listę. Spróbuj się zdebugować, albo wypisać wartość, którą zmieniasz zaraz po wpisaniu wartości. Wtedy będziesz wiedział, że to działa.

2

Mój błąd. Nie zauważyłem że jest to struktura. A elementy struktury są przekazywane przez wartość nie przez referencje...

ModbusReg temp = new ModbusReg();
for (int i = 0; i < 10; i++)
temp.listregs.Add(new ModbusReg.UserReg() { value = (ushort)i });

var userReg = temp.listregs.ElementAt(3);
userReg.value = 1000;
temp.listregs[3] = userReg;

Jeżeli nie możesz zrezygnować ze struktury to jest takie wyjście. Jeżeli będziesz dużo zmieniał taką listę to zastanów się nad użyciem klasy.

0

Ok, to inaczej. Czy mógłbyś mi napisać linijkę kodu zmieniającą wartość pola elementu listy zwracanego tym elementat:

modbusreg.listregs.ElementAt(index)

Próbowałem tak:

modbusreg.listregs.ElementAt(index).value = 5;

ale wywala błąd przy kompilacji....

0

Dzięki, działa, podmiana elementu listy spełniła moje oczekiwania. Pozdrawiam

0

Mam jeszcze nieco inne pytanie.
Mam takie coś:

        private void textBox3_TextChanged(object sender, EventArgs e)
        {
            UInt32 temp = 0;

            /* check if correctly number value has entered , if not than clear the register address in textbox */
            try
            {
                temp = Convert.ToUInt32(textBox3.Text.ToString(), 16);
            }
            catch
            {
                
            }
            if (!((temp > 0) && (temp < 65536))) { textBox3.Text = "0x"; textBox3.SelectionStart = 2; }
        }

to oczywiście obsługa zdarzenia od zmiany tekstu w textboxsie.
Jak widać w tej obsłudze zdarzenia mam instrukcję textBox3.Text = "0x", czyli zmianę tekstu, czy istnieje ryzyko że zanim skończy się wykonywać obsługa tegoż zdarzenia po raz wtóry zostanie zawołana ta procedura obsługi tegoż zdarzenia ?

1

Zgodnie z dokumentacją https://msdn.microsoft.com/en-us/library/system.windows.forms.control.textchanged(v=vs.110).aspx event będzie wywołany albo przez modyfikację w kodzie albo przez modyfikacje użytkownika. Więc istnieje możliwość, że zapętlisz się przez takie zmiany wartości. Pamiętaj tylko że jest to wywoływane jednowątkowe tzn nie ma możliwości że naglę będzie w jednym czasie zmieniał i odczytywał wartość.

0

Wie ktoś czy jeśli jakieś zdarzenie cyklicznie zapisuje metodą AppendText do richtextbox to czy może on się przepełnić czego skutkiem będzie błędne działanie programu ?

0
Adamos19 napisał(a):

Wie ktoś czy jeśli jakieś zdarzenie cyklicznie zapisuje metodą AppendText do richtextbox to czy może on się przepełnić czego skutkiem będzie błędne działanie programu ?

Raczej wyjątek jakiś wyleci, tak się problemy rozwiązuje w obiektowych językach.

0

Ok, rozumiem Twoje stanowisko, w moim programie jednak dzieją się rzeczy naprawdę przypominające to że wyjątek nie wyskakuje a program ni stąd ni zowąd zaczyna szaleć...
napiszę więcej tylko jak będę miał chwilkę bo aktualnie mocno obciążony jestem...

0

Potrzebuję pomocy.
Nie potrafię zmienić wartości pola oryginalnego elementu listy.
Załóżmy że lista jest listą struktur:

public struct UserReg
{
    public string name;
    public UInt16 value;
}
public List<UserReg> listregs;

private void Change()
{
    UserReg v = listregs.ElementAt(index);
    UserReg t = new ModbusReg.UserReg() { value = 3, name = v.name };
    modbusreg.listregs[index] = t;
}

To znaczy potrafię (jak wyżej) ale robię to bardzo karkołomnie, to jest tworzę nowy element listy z podmienioną wartością po czym zmieniam referencję wybranego elementu listy na nowy element a na barki garbage kolektora zrzucam zwolnienie pamięci przydzielonej na oryginalny element.... mi się to niepodoba, a Wam ? Kto zna inne rozwiązanie ?

0

Słuchajcie jeszcze jedno co do powyższego.
Nie potrafię znaleźć indeksu elementu tej listy dla którego wartość pola przykładowo pola name będzie odpowiednia, np. równa "Adam". To znaczy potrafię ale robię to znowu bardzo karkołomnie, wolałbym nie pokazywać kodu na razie. Coś czuję że możnaby wykorzystać takie coś:

modbusReg1.listregs.FindIndex()

ale argumentem tej metody jest jakiś Predicate a ja kompletnie nie wiem co to jest predykat w c#...
sugerując się hintem wyświetlanym przez visuala wygląda na to że tam właśnie mógłbym wpisać warunek który mnie interesuje czyli name == value ale na pewno nie łyka go w formie którą zapisuję, trzeba to jakoś specyficznie wpisać, ktoś pomoże ?

0
Adamos19 napisał(a):
name == value // jest złe, 

ale jest pewnie takie coś

name.equals(value)
1

ale argumentem tej metody jest jakiś Predicate a ja kompletnie nie wiem co to jest predykat w c#...
sugerując się hintem wyświetlanym przez visuala wygląda na to że tam właśnie mógłbym wpisać warunek który mnie interesuje czyli name == value ale na pewno nie łyka go w formie którą zapisuję, trzeba to jakoś specyficznie wpisać, ktoś pomoże ?

Predykat to najogólniej mówiąc funkcja orzekająca o spełnieniu warunku, a co za tym idzie, funkcja która jest typu takiego, że a -> Bool. Mówiąc bardziej po ludzku - do funkcji FindIndex musisz jako parametr przekazać funkcję, która przyjmuje obiekt takiego typu, jak element listy (u ciebie struktura UserReg), a zwraca Boolean. Aby sobie skrócić zapis możesz użyć funkcji zapisanej jako wyrażenie lambda.

Stąd:

var index = modbusReg1.listreg.FindIndex(x => x.name == "Adam"); // x będzie typu takiego, jak trzeba - u ciebie prawdopodobnie UserReg
Mały Karp napisał(a):

ale jest pewnie takie coś

name.equals(value)

To jest normalny język programowania C#, a nie Java, operator == jest przeciążony dla stringów.

I mam prośbę: jak masz nowy problem, załóż nowy temat - w szczególności nie pytaj o nowe rzeczy w temacie, w którym już zaznaczyłeś odpowiedź jako zaakceptowaną.

0

Zrobiłem tak:

ModbusReg.UserReg x = new ModbusReg.UserReg();
var index = modbusReg1.listregs.FindIndex(yx => (x.name == "Adam"));

i pomimo że w liście mam jeden element typu UserReg którego pole name równe jest Adam to nadal index ustalany jest na -1 co świadczy o tym że wpisany przeze mnie odcinek kodu jest błędny. Jeśli zamiast yx dam x to wyrzuca błąd:

A local variable named 'x' cannot be declared in this scope because it would give a different meaning to 'x', which is already used in a 'parent or current' scope to denote something else.
Nie wiem jak to napisać żeby było dobrze.

Musiałbym napisać swoją funkcję którą bym przekazał jako predykat. Za chiny ludowe nie potrafię tego napisać przy użyciu wspomnianego przez Ciebie tego lamda wyrażenia....

I obiecuję że zastosuję się do wskazówek formalnych o których wspominałeś.

0

Heh, problem polega na tym, że już masz zmienną x w swoim kodzie, wcześniej, i ci się powtarza zmienna. Jak zmienisz x na yx w jednym tylko miejscu, to potem szuka ci nie do końca tego, co chcesz.

var index = modbusReg1.listregs.FindIndex(yx => (yx.name == "Adam"));
0

Aha, no faktycznie. Dzięki. Teraz działa jak należy. Czy poruszony przeze mnie temat (patrz wyżej w historii tego wątku) dot. podmiany wartości pola elementu listy można już załatwiać w tym wątku? Mógłby się ktoś do tego jeszcze odnieść ? Może w tym też byś mi pomógł kolego @Ktos ?
Mam jeszcze takie pytanie: co w języku c# oznacza var, czemu deklarujemy index jako var a nie po prostu int lub object ?

2

Czy poruszony przeze mnie temat (patrz wyżej w historii tego wątku) dot. podmiany wartości pola elementu listy można już załatwiać w tym wątku? Mógłby się ktoś do tego jeszcze odnieść ? Może w tym też byś mi pomógł kolego @Ktos ?

Rozwiązanie jest proste, i wspomniane wyżej: nie używaj struktur ;-) Dlaczego musisz używać struktur? Jedną z zasad dotyczących ich tworzenia jest właśnie to, że powinny być niezmienne (immutable).

Mam jeszcze takie pytanie: co w języku c# oznacza var, czemu deklarujemy index jako var a nie po prostu int lub object ?

var to typ domniemany - taki, jaki akurat będzie dobry. Różne są konwencje używania var w C#, najczęściej mówi się, że można spokojnie użyć jeżeli jest jasne jakiego typu będzie wynik operacji po prawej stronie przypisania - w przypadku FindIndex to jasne jest, że będzie to zapewne jakiś int albo uint. W zasadzie czy napiszesz sobie int czy var nie ma totalnie znaczenia.

1 użytkowników online, w tym zalogowanych: 0, gości: 1