inheritance - exercise - c#

Alright, so I'm currently learning inheritance, and I've done something, this is the code:
class array
{
int [] arr;
public array(int[] arr)
{
this.arr = arr;
}
public int Biggest()
{
return arr.Max();
}
public int Min()
{
return arr.Min();
}
public int SumArr()
{
return arr.Sum();
}
}
class array2 : array
{
public array2(int [] arr):base(arr)
{
}
public double Average()
{
return
}
}
Now, in the derived class I need to get the average of the array and I can't do arr.Average()
The error says: Error 1 'ConsoleApplication1.array.arr' is inaccessible due to its protection level C:\Users\x\AppData\Local\Temporary Projects\ConsoleApplication1\Program.cs 35 20 ConsoleApplication1
Anyone can tell me what am I doing wrong?
Thanks for helpers!

arr is declared as private since you didn't specify a visibility type. If you change it to protected, then your subclass array2 will be able to access it.
protected int [] arr;

In your example, you've made the arr array implictly private where you have omitted the modifier itself. If you want to provide access to said field in your derived classes, you'd need to use an access modifier of protected:
protected int[] arr;
But it's not recommend to expose fields this way, as fields should really be for private class state. What you should do, is encapsulate read-only access to that field, via a property:
protected int[] Array {
get { return this.arr; }
}
Which means in your derived class, you can:
public double Average()
{
return this.Array.Average();
}

In C#, the default access level for a class member is private. You haven't specified an access level for int [] arr, so it is private and hence visible to the other class.

That's because your arr field is private. consider using a write-private read-protected property instead, like this:
class array
{
protected int[] arr {get; private set; }
public array(int[] arr)
{
this.arr = arr;
}
public int Biggest()
{
return arr.Max();
}
public int Min()
{
return arr.Min();
}
public int SumArr()
{
return arr.Sum();
}
}
class array2 : array
{
public array2(int [] arr):base(arr)
{
}
public double Average()
{
return arr.Average();
}
}

Since you didn't explicitly define an access type for arr, it is implicitly set to private. To be able to access this from the derived class, you should set it to protected.
protected int [] arr;
There are better ways to do this, e.g. through a property, but that's the general idea.

Add public or protected to the arr variable:
public int [] arr;
protected int [] arr;
If you don't specify otherwise, the compiler will default to making your declarations private.

Related

C# Non-generic method in generic class

Am trying to define a class that provides a random number between two values. It shall work with ints as well as with floats.
To only have a single class, I'd like to use generics.
This works well for the member variables, but how do I define a method for only specific types?
The Random.Range method I use (from unity) can accept floats or ints so a cast is needed. The generic type does not seem to be castable at all however.
Have written this code to show what I am looking for. Does a syntax similar to this exist?
public class MinMaxSetting<T>
{
public T min;
public T max;
public MinMaxSetting(T min_val, T max_val)
{
min = min_val;
max = max_val;
}
public T GetRandom<int>()
{
return Random.Range((int)min, (int)max);
}
public T GetRandom<float>()
{
return Random.Range((float)min, (float)max);
}
}
Found a solution: Extension Methods!
Surely a bit quirky but it does what it's supposed to and it's readable.
public class MinMaxSetting<T>
{
public T min;
public T max;
public MinMaxSetting(T min_val, T max_val)
{
min = min_val;
max = max_val;
}
}
// Helper class just for the extension methods. The name is irrelevant.
public static class MinMaxSetting
{
public static float GetRandom(this MinMaxSetting<float> self)
{
return UnityEngine.Random.Range(self.min, self.max);
}
public static int GetRandom(this MinMaxSetting<int> self)
{
return UnityEngine.Random.Range(self.min, self.max);
}
}
Example:
public static void Main()
{
MinMaxSetting<float> my_setting = new MinMaxSetting<float>(5.3f, 20.4f);
Console.WriteLine(my_setting.GetRandom());
}

How do I give a class an array that can be accessed by class methods?

I have just started learning OOP. I am making my own class which builds on an array. It has an attribute called length and an array that is of that length.
However, the actual value of length is only declared in the constructor, so my array is stuck as a private variable within the constructor.
How do I implement one such that the array has a certain user-chosen length and is able to be accessed by the class' methods?
public class myClass
{
private int length; //This is an attribute of my class
public myClass(int myLength)
{
length = myLength;
int[] myArray = new int[length];
}
}
I want myArray to be accessible but this is not possible because it is a local variable in the constructor. I think if it was in Python I could just make it a global variable. (Although I think that I would still like to keep this array private as it is also an attribute).
Thanks!
Note: This is not homework but rather something I've been challenging myself to do.
Here's how your class could look like, the OOP way:
public class MyClass
{
public readonly int Length;
public int[] Data { get; private set; }
public MyClass(int dataLength)
{
Length = dataLength;
Data = new int[dataLength];
}
}
Here:
The Data array is constructed with the user-specified length.
You can access both Length and Data from inside and outside the class
Once instantiated, the Length property cannot be modified
Another way would be to make Length return directly the Length property of the array, as long as it was instantiated:
public class MyClass
{
public int Length { get { return Data == null ? 0 : Data.Length; } }
public int[] Data { get; private set; }
public MyClass(int dataLength)
{
Data = new int[dataLength];
}
}
Revised answer as you have added more code to the question:
You have unwittingly solved your own problem. Take a look at your private int length; declaration. After the object the initialized with the constructor public myClass(int myLength), the length variable is still accessible within the object.
The sample code below has a new public int GetLengthPlusOne() method to access the length variable. Similarly, you can now use the myArray variable in another method.
MyOtherClass
public class MyOtherClass
{
public void SampleMethod()
{
MyClass cls = new MyClass(5);
Console.WriteLine(cls.GetLengthPlusOne()); //Output: 6
var arr = cls.myArray;
}
}
MyClass
public class MyClass
{
private int length; //This is an attribute of my class
/*
* Declaring this within the class instead of the constructor allows it
* to be persisted in an instance of the class. This is a property.
*/
public int[] myArray { get; set; }
public MyClass(int myLength)
{
length = myLength;
myArray = new int[length];
}
public int GetLengthPlusOne()
{
return length + 1;
}
}
Side note on naming conventions:
For C#, Class names start capitalized (MyClass), whilst instances of a class start with a lower-case (myClass). Have a look at the documentation for more info.

Is there any better way to encapsulate an array?

How I do it currently:
class Foo
{
public int[] A { get { return (int[])a.Clone(); } }
private int[] a;
}
I think it's bad because it creates a clone and casts whenever I access it. I know I can work around it by introducing an additional variable like this
var foo = new Foo();
// as soon as you have to access foo.A do this
int[] fooA = foo.A;
// use fooA instead of foo.A from now on
but still it just looks bad.
I also dislike the java way of encapsulating
int get(int index) { return a[index]; }
because I dont get the advantages of using an array.
Is there any better way to do this?
edit: I want an array of encapsulated variables. The problem is that
public int[] A { get; private set; }
is not an array of encapsulated variables because I can modify elements of the array from outside of the class.
edit: It should also work with multidimensional arrays
Arrays implement IReadOnlyList<T> which exposes all of the relevant information you want (an iterator, an indexer, count, etc.) without exposing any of the mutable functionality of the array.
class Foo
{
public IReadOnlyList<int> A { get { return a; } }
private int[] a;
}
alternatively, you could use an iterator/generator to return the items as requested:
class Foo
{
public IEnumerable<int> A
{
get
{
foreach (int i in a)
yield return i;
}
}
private int[] a;
}
... then iterate over them normally or use LINQ to get them as a new array or other type of collection:
int[] arr = foo.A.ToArray();
Why not expose A as a implementation of IReadOnlyList
class Foo
{
public IReadOnlyList<int> A { get { return a; } }
private int[] a;
}
This allows you to return the Array as a collection where they can use the index but cannot change the contents of the array itself.
sounds like you need an indexer
...
public int this[int i]{
get{return a[i];}
set{a[i] = value;}
}
....
https://msdn.microsoft.com/en-us/library/6x16t2tx.aspx

Read property from the same class

In C# if I have this in a class:
public int SomeNumber
{
get { return 6; }
}
How can I read (get) that number from a function in the same class if the function receives a variable with the same name? Example:
public bool SomeFunction(int SomeNumber)
{
check if SomeNumber (the one passed to this function) == SomeNumber (the one from the public int)
}
You would simply invoke the property get in the method:
public void MyMethod()
{
var someNum = SomeNumber; // basically, var somNum = this.SomeNumber;
}
EDIT: To clarify with OP's edit:
public void MyMethod(int someNumber)
// Change the naming of your parameter so it doesnt clash with the property
{
if(someNumber == SomeNumber)
// Do Stuff
}
Same as if it were a field:
public void SomeOtherFunction()
{
var x = SomeNumber;
}
Although the other suggestions do work well (and adhere to easier to read/maintain code), they don't directly answer your question. Given a class
public class SomeClass
{
public int SomeNumber { get { return 6; } }
...
And a function with a parameter passed in
public void SomeMethod(int SomeNumber)
{
// Your code here...
You can access the passed in parameter and property like so:
if (SomeNumber > this.SomeNumber)
{
// Your results here
The distinction is that if you refer to just the variable name, it will use the variable from the same scope, i.e. the passed in variable. If you specify use "this." then you always get the class member.
Note: This does not work with Static classes, as there is no instance of the class. (Can't use "this.whatever") and you will be stuck. There are many coding Standards out there and some of them states that it is best practice to use the form "myVariable" for method parameters, "MyVariable" for property names, and _myVariable for property backing stores, to easily distinguish between them in your code.
public class FavoriteNumber
{
public int SomeNumber
{
get { return 6; }
}
Public int Twelve()
{
return SomeNumber*2;
}
}
Please run this code and you will get it.. Use this operator to refer the class level variale.
public void CheckNumber(int SomeNumber)
{
Console.WriteLine(SomeNumber);
Console.WriteLine(this.SomeNumber);
}

Array property syntax in C#

I have a a class that has an integer array property and I am trying to figure out the right syntax for it. The integer array gets instantiated in the class constructor.
class DemoClass
{
private int[] myNumbers;
public int[] MyNumbers
{
get { /* Some logic */ }
set { /* Some logic */ }
}
public DemoClass(int elements)
{
// Here, the array should get instantiated using the elements.
}
}
How does the get/set block syntax work if I want my client code to retrieve a number from the array through the property MyNumbers?
How can I send it the right index?
What do I have to initialize?
Are you looking for:
class DemoClass
{
public int[] MyNumbers { get; private set; }
public DemoClass(int elements)
{
MyNumbers = new int[elements];
}
}
As for normal properties that do nothing except publicize a private field (as you seem to want):
private int[] myNumbers;
public int[] MyNumbers
{
get { return myNumbers; }
set { myNumbers = value; }
}
CA1819: Properties should not return arrays
http://msdn.microsoft.com/en-us/library/0fss9skc.aspx
Arrays returned by properties are not write-protected, even if the property is read-only. To keep the array tamper-proof, the property must return a copy of the array. Typically, users will not understand the adverse performance implications of calling such a property. Specifically, they might use the property as an indexed property.
To fix a violation of this rule, either make the property a method or change the property to return a collection instead of an array
If the number of element in the array is fixed, I would only provide a getter for the array and leave off the setter. You will still be able to assign values to individual elements in the array, but this will prevent someone from swapping the whole array out from under you (or setting it to null. The code would look like this:
class DemoClass
{
public int[] MyNumbers
{ get; private set; }
public DemoClass(int elements)
{
MyNumbers = new int[elements];
}
}
If the number of elements are not fixed, then you should use a List<int> rather than an array, and then you definitely want a property with no setter.
class DemoClass
{
private int[] myNumbers;
public int[] MyNumbers
{
get { return myNumbers; }
set { myNumbers = value; }
}
public DemoClass(int[] elements)
{
myNumbers = elements;
// Here, the array should get instantiated using the elements.
}
}
It is called Auto-Implemented Properties . So if you have syntax like
public int[] MyNumbers { get; set; }
C# compiler will automatically create for you backing field. This feature was introduced in C# 3.0, and before that you always had to implement property with backing field.
You can read more at: New C# "Orcas" Language Features: Automatic Properties, Object Initializers, and Collection Initializers
class DemoClass
{
private int[] myNumbers;
public int[] MyNumbers
{
get { return myNumbers; }
set { myNumbers = value;}
}
public DemoClass(int elements)
{
// Here, the array should get instantiated using the elements.
MyNumbers = new int[5] { 1, 2, 3, 4, 5};
}
}

Categories