Jak radzicie sobie z niemożnością użycia słowa kluczowego const podczas przekazywania parametrów do funkcji (w taki sposób w jaki można to wykonać w c++) ?
- Rejestracja:ponad 9 lat
- Ostatnio:prawie 9 lat
- Postów:55
Czasem użyteczne jest zagwarantowanie, że dany argument przekazany do funkcji nie zostanie zmieniony. Albo zagwarantowanie, że dana metoda nie zmieni pól obiektu. W c++ można to było osiągnąć poprzez użycie słowa "const". W C# nie widzę takiej możliwości ?

- Rejestracja:prawie 14 lat
- Ostatnio:prawie 3 lata
- Postów:4882
ogolnie się nie da. Jest obejscie problemu... ale nie warto
http://stackoverflow.com/questions/3799062/const-methods-in-c-sharp
pamietaj C# to nie C++. Nie przenos ideologii jednego jezyka na drugi. Przewaznie to nie dziala.

- Rejestracja:około 17 lat
- Ostatnio:około 4 godziny
- Lokalizacja:Wrocław
To nie jest jakiś duży problem, bo:
- W przypadku typów wartościowych takie zachowanie jest domyślne. Żeby móc zmienić w metodzie wartość parametru tak, aby była widziana poza nią, należałoby przekazać go jako
out
lubref
. - W przypadku typów referencyjnych w metodzie nie podmienisz obiektu (no chyba, że użyjesz
out
alboref
). - Jeśli o pola typów referencyjnych chodzi, to wystarczy, żeby klasa nie dawała możliwości zmiany takich pól.
Reasumując - aby osiągnąć to, czego potrzebujesz - wystarczy tak definiować klasy, aby obiekt po utworzeniu był niezmienny, oraz nie używać out
i ref
.
P.S. Stosowanie ref
i out
to w ogólności okropna praktyka prowadząca do powstawania syfiastego kodu.

return
. Jeśli chcesz zwrócić kilka wartości z funkcji, to stwórz klasę która te wartości będzie zawierała i zwracaj obiekt tej klasy.

- Rejestracja:ponad 9 lat
- Ostatnio:prawie 9 lat
- Postów:55
Przekazując do funkcji argument int[,] zapomnialem, ze to przeciez typ referencyjny! Przypisujac wiec wartosci do poszczegolnych elementow tablicy dzialalem nie na kopii, lecz na wlasciwym obiekcie. W tym momencie zaczalem wlasnie rozwazac uzycie slowa const, i stad moje pytanie.
- Rejestracja:około 22 lata
- Ostatnio:2 miesiące
- Postów:5042
Chodzi o to, że zwracam jakiś obiekt. Dajmy na to jakąś listę. I chcę mieć pewność, że tej listy mi nikt nie zmieni. Np. nie doda żadnego elementu, nie usunie, a nawet nie zmodyfikuje żadnego elementu listy. Np:
List<MyObj> list = obj.GetList();
//i teraz bym chciał, żeby np. nie było możliwe zrobienie:
list.Add(new MyObjs());
//ale też bym chciał, żeby nie było możliwe:
list[0].OneProperty = newValue;

- Rejestracja:około 17 lat
- Ostatnio:około 4 godziny
- Lokalizacja:Wrocław
@Juhas, jeśli chcesz, aby niemożliwa była modyfikacja kolekcji, to nie przekazujesz List<T>
, która na to pozwala, lecz IEnumerable<T>
. Jeśli nie chcesz modyfikować właściwości poszczególnych elementów, to uczyń je niemodyfikowalnymi, po prostu nie definiuj publicznych seterów.
- Rejestracja:około 22 lata
- Ostatnio:2 miesiące
- Postów:5042
No właśnie nie mogę nie robić publicznych setterów. Tzn. inaczej. Mam problem podobny do gościa, który pytał o ruchy królowej. Mam jedną klasę, która może modyfikować obiekty innej klasy. Ale inne klasy mogą jedynie odczytywać te obiekty. Ideałem byłoby c++ friend albo zwracanie obiektu przez stałą referencję. Innej możliwości nie widzę. No, pozostaje jeszcze Reflection, ale jednak wolałbym unikać takich fikołków.

- Rejestracja:około 17 lat
- Ostatnio:około 4 godziny
- Lokalizacja:Wrocław
Można też mieć różne zestawy obiektów - jeden mutowalny, używany przez te dwie klasy, które mogą mutować, drugi niemutowalny, dostępny dla reszty aplikacji.
Generalnie większość problemów idzie rozwiązać dobrą architekturą - może po prostu brakuje Ci jakiegoś wzorca, który pozwoliłby Ci tworzyć obiekty raz i nie trzeba byłoby ich modyfikować?
- Rejestracja:około 22 lata
- Ostatnio:2 miesiące
- Postów:5042
Nie, no właśnie potrzebuję je modyfikować, ale tylko w tej jednej klasie. A co z tymi zestawami obiektów? Znasz jakiś dobry wzorzec do tego? Bo póki co to moim rozwiązaniem jest zwracanie kopii takiej listy. Ale wiadomo, jakie to rozwiązanie, zwłaszcza jak lista jest duża.

- Rejestracja:ponad 22 lata
- Ostatnio:4 dni
A próbowałeś coś przypisać do elementu ReadOnlyCollection?


- Rejestracja:około 17 lat
- Ostatnio:około 4 godziny
- Lokalizacja:Wrocław
Juhas napisał(a):
Nie, no właśnie potrzebuję je modyfikować, ale tylko w tej jednej klasie. A co z tymi zestawami obiektów? Znasz jakiś dobry wzorzec do tego? Bo póki co to moim rozwiązaniem jest zwracanie kopii takiej listy. Ale wiadomo, jakie to rozwiązanie, zwłaszcza jak lista jest duża.
Jeśli zrobisz drugi zestaw obiektów, tak jak ja proponowałem, to i drugą listę będziesz musiał mieć.
Mi chodzi o coś takiego:
class Student
{
public string Name { get; set; }
}
class ImmutableStudent
{
public string Name { get; private set; }
public ImmutableStudent(Student s)
{
this.Name = s.Name;
}
}
I jak już masz gotową kolekcję obiektów Student, z już poustawianymi wartościami, to tworzysz listę obiektów ImmutableStudent
, i jej używa reszta klas w aplikacji. Innego sposobu nie znam.
ŁF napisał(a):
List<T>.AsReadOnly
=>ReadOnlyCollection<T>
Tylko trzeba pamiętać, że ReadOnlyCollection
wcale nie jest takie znowu read only:
var studentsList = new List<Student>()
{
new Student { Name = "A" },
new Student { Name = "B" },
new Student { Name = "C" },
};
var readonlyStudents = studentsList.AsReadOnly();
studentsList.Add(new Student { Name = "readonly nie działa" });
foreach (var student in readonlyStudents)
{
Console.WriteLine(student.Name);
}
Jak się chce mieć naprawdę niezmienną kolekcję, trzeba skorzystać z czegoś z przestrzeni System.Collections.Immutable
- i trzeba to sobie ściągnąć z NuGeta, bo w standardowym frameworku tego nie ma.
Złoty Młot napisał(a):
jak wspomniano wcześniej - zamień elementy kolekcji na strukturę
Tylko bez przesady. Zamiana klasy na strukturę to generalnie jest zły pomysł. Strukury się stosuje w określonych przypadkach i taki typ musi spełniać określone warunki, żeby miał sens jako struktura.
- Rejestracja:około 10 lat
- Ostatnio:prawie 6 lat
- Postów:329
Możesz spróbowac tak, jak wymyślisz jakieś sprytne dziedziczenie lub delegacje FriendClass(nie koniecznie słowem delegate ;) ) i fabryke by nie pisać tej śmiesznej podwójnek kropki tysiąc razy to to rozwiązanie może mieć ręce i nogi
class NormalClass
{
public string Name{ get; protected set; } // by można było dziedziczyć po normal class
public string Surname { get; protected set; }
public class FriendClass
{
public void SetFrienName(NormalClass friend, string name)
{
friend.Name = name;
}
public void SetFrienSurname(NormalClass friend, string surname)
{
friend.Surname = surname;
}
}
}
albo
class NormalClass
{
private void DoSomething()
public class FriendClass : NormalClass
{
public void Do()
{
base.DoSomething();
}
}
}
Gdby friendClass i normal class miały długie implementacje mozesz zastosować słowo partial i zrobić każdą w osobnym pliku.
Jeśli to co zrobiłem wyżej zrobisz static, to bedziesz mógł napisać interface IFriend i do pisać do niego jako metode rozszerzeń SetFrienSurname, SetFrienName, a to pozwali Ci obdarzyć dowolną klase w programie implementującą IFriend dostępem do pól i metod prywatnych normalClass :D
ps pisalem wcześniej w komentarzu.
Zarejestruj się i dołącz do największej społeczności programistów w Polsce.
Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.