Trying to understand indexers in C# [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am trying to understand indexers in C#. In the accepted answer, I am not able to understand how:
public float this[int index]
{
get{
return temps[index];
}
set{
temps[index] = value;
}
}
works. As in what if I have 2 float variables?

To put it simply, Idexers is a technique that you can use to allow a class to behave in a similar way to an array, by allowing you can access values by using an index.
generally you would only do this if conceptually the class is supposed to behave like an array, its primary function is to hold a single collection of other objects.
A common scenario is when the class is a wrapper for an internal array variable that you do not want to directly expose. We try to avoid classes inheriting from arrays or IEnumerable because there is a lot of functionality to implement, but wrapping an array for the purposes of adding additional functionality can make a lot of sense.
temps in your syntax public float temps this[int index] doesn't make sense, and is not necessary because a class can only have a single indexer of each type.
Instead of using an indexer, if the temps field was exposed as public, then you could use this syntax instead to access the value for the index of 5:
TempratureRecord oTest = new TemperatureRecord();
var tempAtIndex5 = oTest.temps[5];
But now you have access to the temps variable itself, meaning you could reassign it altogther.
Do not mistake that example as the only way to expose values from internal arrays, if you had multiple arrays then you can expose them in different ways, generally NOT by using an indexer.
If the indexer only exposes an internal array, but offers nothing more, then that's probably not a great reason to use them at all.
You can have an indexer of say type string and a separate indexer of type int, this is a common pattern if the internal array is an array of objects that might have both a unique string and int property that can be used to identify the correct object to return.
However you would not generally do this just because you have an array of ints and an array of strings. The general expectation of Indexers is that if there are multiple indexers, we are offering the caller a different way to access the same conceptual list of objects, and indeed to target the same object in different ways, perhaps because we do not know the index of that object in the internal array.
An example of how multiple indexers might be used to access the same internal array, but showing how the index passing in doesn't have to be the index at all that is used internally:
Note: by doing it this way, it may not make sense to allow a setter at all
public class Person
{
string Name { get; set; }
int Id { get; set; }
}
public class People
{
private Person[] _backingStore;
/// <summary>Instantiate a new list of people</summary>
public People(params Person[] persons)
{
_backingStore = persons;
}
/// <summary> Return a person from this list by Id </summary>
public Person this[int id]
{
get{
return _backingStore.Where(p => p.Id == id).FirstOrDefault();
}
}
/// <summary> Return a person from this list by Name </summary>
public Person this[string name]
{
get{
return _backingStore.Where(p => p.Name == name).FirstOrDefault();
}
}
}
...
People list = new People(
new Person(){ Id = 26, Name = "Hassan" },
new Person(){ Id = 101, Name = "John Skeet" }
);
var john = list["John Skeet"];
var alsoJohn = list[101];
var no1 = list["someone else"];
var hassan = list["Hassan"];

Related

Why does Equals method of attributes compare fields? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
When I checked the attributes for equality, I noticed that they already have Equals method that compares the fields. For custom classes this comparison does not occur, since it is bad for performance, but why was an exception made for attributes?
Here's the code to make sure:
public class MyAttribute : Attribute
{
public int Value { get; }
public MyAttribute(int value) => Value = value;
}
public class MyClass
{
public int Value { get; }
public MyClass(int value) => Value = value;
}
public class Test
{
[Test]
public void TestEquals()
{
var myAttributeLeft = new MyAttribute(1);
var myAttributeRight = new MyAttribute(1);
var attributeEqualityResult = myAttributeLeft.Equals(myAttributeRight);
Console.WriteLine(attributeEqualityResult); // true
var myClassLeft = new MyClass(1);
var myClassRight = new MyClass(1);
var classEqualityResult = myClassLeft.Equals(myClassRight);
Console.WriteLine(classEqualityResult); // false
}
}
Custom attributes are not intended for use as domain objects: they are explicitly intended to represent metadata that are hard-coded at compile time. Assuming they are used as intended, this gives them a few special properties:
There are limits on the types that they are allowed to use: typically native types like int and string, and arrays of those native types.
The number of items that could be put into an array on the type is bounded by the number of items that are written into an actual code file.
In domain models it could create enormous performance penalties to compare the values of fields, properties, and elements of collections: you don't know how big the object structure for a given class might be, and a collection could have millions of items in it. But the restrictions mentioned above mean that the cost of an equality comparison for custom attributes is pretty well bounded. Evidently the creators of .NET felt that this made it worthwhile to give the base class value semantics, although the documentation includes remarks that recommend overriding the default implementation to use object equality or hard-coded value semantics instead.
Short answer: System.Attribute implements its own implementation of Equals which is different from the one in System.Object (from which MyClass class inherits)
You can find a more detailed answer on ms docs

Leave the type of a List in a class vague until populated [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
In a user-defined class, I'd like to leave the type of a List ambiguous so that I could have a list of strings or integers or tuples in separate instances of the class (that is to say, each list would be of only one type, but different instances of the class would different types). I currently have something like:
public Result
{
private List<dynamic> _vaguelist;
public List<dynamic> vaguelist {
get
{
return _vaguelist;
}
set
{
_vaguelist = value;
}
}
}
But, I'm pretty sure I'm not using the dynamic type properly. I think I would need a constructor that creates a new List where T gets determined from the GetType() of the first value added to the Class. Or write the List to be designated a certain type when it is initialized.
In short, how can I define a list within a class such that the type of its values can either be inherent of whatever is added to the list or specified when the class is instantiated? (values within a single list will all be of ONE type).
I think you have two options, the first one beign the best approach, will only work if you know the list will be of a certain type.
public class Result<T>
{
private List<T> _vaguelist = new List<T>();
public List<T> vaguelist {
get
{
return _vaguelist;
}
set
{
_vaguelist = value;
}
}
}
Result a = new Result<string>();
a.vaguelist.Add("1234");
Result b = new Result<int>();
a.vaguelist.Add(1234);
The second option will work if you wan't to add more than one type into the list o you won't know what you're putting into the list
public class Result
{
private List<object> _vaguelist;
public List<object> vaguelist {
get
{
return _vaguelist;
}
set
{
_vaguelist = value;
}
}
}
Result a = new Result();
a.vaguelist.Add("1234");
a.vaguelist.Add(1234);
The problem with this approach is that you will have to cast every single item in the list in order to take advantage of the type the item is.
Making use of the first approach, you could implement it like this:
public class Result<T>
{
private List<T> _vaguelist = new List<T>();
public List<T> vaguelist {
get
{
return _vaguelist;
}
set
{
_vaguelist = value;
}
}
}
public abstract class Result
{
public static Result<T> NewResultFromItem<T>(T item)
{
Result<T> result = new Result<T>();
result.vaguelist.Add(item);
return result;
}
}
string item1 = "123";
string item2 = "234";
var result = Result.NewResultFromItem(item1);
result.vaguelist.Add(item2);
You are asking for both type safety and type agnosticism (I just made up that word), which you cannot have both at the same time. Suppose you would find a way to make the list flip to a type safe collection at runtime when the first item is added. Who or what would be able to use it as such if you cannot code against it? The compiler will not know what it is going to be at runtime so there is not much that can be done for type safety. At runtime you would still have to figure out what you are dealing with so from a coding perspective it would still be just a list of objects.

creating dynamic 2d array that automatically adjusts based on list in c# wpf

Suppose I have a list of objects of a C# class. I wish to have a 2d array (or list of lists, or something else that can do the same) that can hold information of the relations between all objects in the list. The class could look like this:
public class SimplePoint
{
public string strName{ get; set; }
};
public class SimpleRoute
{
public int iDistance{ get; set; }
};
public class Place
{
public ObservableCollection<SimplePoint> points;
// Below array should dynamically increase/decrease size
// depending on length of list of points
// The array should store 2 values for each possible set of points:
// distance from x to y, and distance from y to x
public SimpleRoute[, ] routes;
};
The 2d array/table should have one row and one column for every element in the list. When an element is added to the list, the 2d array should grow in two directions, and when an element is deleted, the table/array should shrink in two directions.
The two dimensional array as declared in the above code will obviously not work for this. Rather, I am wondering if the 'SimpleRoute' class could somehow abserve the ObservableCollection 'points', and internally maintain the table of distance data.
Later I wish to also be able to store the data from the 2d array/table - or from the class behind/around it - in an XML (through serialization) and be able to load it again (through deserialization). The relation to the list of 'SimplePoints' should be maintained.
Lastly, the data (ie. the distances) in the automatically adjusting table should editable by the user. I will create the GUI using WPF.
I am wondering what is the best approach for this in C#/.NET, but find it hard to think of something elegant. Searching hasen't yielded a lot of results, though I may be looking in the wrong place.
Maybe there is some easy solution? I am relatively newto .NET programming.
I think that you're asking for information on quite a big domain of .net / general OOP practices, so it's really hard to provide a decent answer without a bit of context, but I'll try to give you some pointers.
I'm assuming you have two classes, say Group and Person, with the following simple definitions:
class Group
{
public string name { get; set; }
public List<Person> Persons = new List<Person>();
}
class Person
{
public string name { get; set; }
public int age { get; set; }
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
}
You have created an object Group with an 1:N relationship to the object Person.
You can test this method with the following test function:
public static void test()
{
Group group =new Group();
group.name= "Friends";
Person p = new Person("John",30);
Person p2 = new Person("Rute",25);
Person p3= new Person("Richard",17);
group.Persons.Add(p);
group.Persons.Add(p2);
group.Persons.Add(p3);
foreach(Person person in group.Persons)
{
Console.WriteLine("{0} is {1} years old. He is in group {2}.",person.name,person.age,group.name);
}
}
Is this what you intended? If you want to create a different type of relationship (N:N, N:1), I can modify my code to help you with that too.

Creating data members of a class in C# [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am a beginner programmer looking for some help with c#.
I am writing a program based on a framework and need to create a data member of a class, then initialize the data member to something.
Next,I need to make a property to get and set the data member.
Also, if someone could provide some information on how to typecast the property that would be great.
I'm just looking for examples and general information here. I checked google and only got links from MSDN but did not understand the content.
Thanks!
Here is a basic explanation, using code:
//Class Definition
public class MyClass
{
//Data Member with inline initialization
private int myInt = 1;
//Standard property
public int MyIntProp
{
get { return myInt; }
set { myInt = value; }
}
//Auto-property, generates the same getter/setter as above with a "hidden" backing property.
public String MyStringProp {get; set;}
//Class constructor, great for initialization!
public MyClass()
{
//Set the property to an initial value
MyStringProp = "Hello World";
}
}
Typecasting is another monster. You have to be careful when doing it, because very few types can be cast to others. The number types can generally be cast to one another (although you can lose data), and derived types can be cast to their base types, but that is about it.
An example (safe) cast of a number would be:
int myInt = 2;
long myLong = (long)myInt;
That is called a "C-Style" cast (because it's how you do it in C) and is generally how you cast numbers. There are other styles and functions to do the cast of course.
#Iahsrah's suggestion is also a good place to start.
A basic type is a class which looks like this:
public class MyType
{
}
You can create a property of this on another class like this:
public class AnotherType
{
public MyType InlinePropertyName { get; set; }
// Simple propertoes require no implimentation (above), or you can explicitly control it all (below)
private MyType _explicitPropertyName;
public MyType ExplicitPropertyName {
get {
return _explicitPropertyName;
}
set {
_explicitPropertyName = value;
}
}
}
The you can easily access from elsewhere in your program like this:
var myType = new MyType();
var anotherType = new AnotherType();
anotherType.InlinePropertyName = myType;

What is the advantage of return ICollection over List [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between List (of T) and Collection(of T)?
I have a static class and a getter to return my List Collection. Now I read and have been told to return ICollection rather than List. What is the advantage of using public static ICollection over public static List?
static class Storage
{
private static List<string> store;
static Storage()
{
store = new List<string>();
}
public static ICollection<string> getList
{
get
{
return store.AsReadOnly();
}
}
public static void addString(string add)
{
store.Add(add);
}
public static void removeString(string remove)
{
store.Remove(remove);
}
public static void display()
{
foreach (String view in store)
{
Console.WriteLine(view);
}
}
}
}
IEnumerable<T> provides access to a forward only cursor over a series of T objects
ICollection<T> provides the same as IEnumerable<T> but also a Count property (meaning the collection has a definitive end)
IList<T> provides the same as ICollection<T> but also random access to any element within the list via an indexer (list[5])
List<T> implements all of the above.
The benefit of using a simpler interface as an argument or return value is that it gives more flexibility to the caller and can help to document how the object will be used (or is intended to be used in the case of a return value).
It's good practice and more maintainable. If you use an interface instead of a type then your code is not hard coded to that type (List).
Example: Say you later decide to change your Storage class to persist your data in another type of storage (i.e., database, XML, etc.) You might use Entity Framework to connect to a database, or your might use LINQ-to-objects.
Actually, you might want to consider using IEnumerable or IEnumerable<string>. These types work very will with LINQ as well as most any other type of collection. Thus you could transition to LINQ without changing the return type and reworking all of the code that deals with your Storage class.
And, perhaps string isn't the best choice either? What are you storing? Maybe you should create a class for the objects you are storing (i.e. Name). Then you would want to return an IEnumerable<Name>.
class Name
{
public string Name { get; set; }
}
Later you might want to add access to FirstName and LastName to your class:
class Name
{
public string Name
get
{
return string.Format("{0} {1}", FirstName, LastName);
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
By using IEnumerable<Name> you don't have to change any of your consuming code to do this--as long as you support the original interface of your Name class you can add the extra features without breaking anything.
Now, if you migrate to a different return type, you should also consider migrating all of the code that deals with Storage to the new type as well. When you 'bake in' the storage type everywhere in your code as List you are making it more difficult to make future changes. You might not appreciate this right now, but as you become a better programmer or find yourself making future changes you will see the benefit of using an interface that permits changing the underlying type. Try to anticipate future possibilities when you select the types of objects and accommodate them in the first revision and you will save headache when you add things later.
If you are asking why return an interface over an object, the interface describes what the object does and how it is used rather than requiring a specific implementation. It makes the code more generic.
If you are asking why a Collection rather than a List, collections do not imply an order whereas a List does. The technical term is that Collections are "weaker" and so apply to more situations. If you do not need ordering, use a Collection. Otherwise, use a List.

Categories