how should i set and get properties values? - c#

I want ask you, how should i set and get properties values? Should i do this, for example directly from another class and set property as public property or maby better practise is to set property as private and change it or get it by using public function implemented in this class?
first case:
//Class.cs
public class Class
{
public int Number{ get; set; }
}
//AnotherClass.cs
public class AnotherClass
{
Class class = new Class();
class.Number = 2;
int number = class.Number;
}
Second case:
//Class.cs
public class Class
{
private int Number{ get; set; }
public void setNumber(int number)
{
Number = number;
}
public int getNumber()
{
return Number;
}
}
//AnotherClass.cs
public class AnotherClass
{
Class class = new Class();
class.setNumber(2);
int number = class.getNumber();
}
this code is obviously a bit simplified ...

I would do that:
//Class.cs
public class Class
{
public int Number { get; set; }
}
//AnotherClass.cs
public class AnotherClass
{
Class class = new Class
{
Number = 2 // use , (comma) to separate if needed when
// the class has other fields
};
int number = class.Number;
}

Related

Creating a property class with no default value and with value

I'm trying to create a property class with a default value and no value. Is this right? If I want a property with no value I'll just call GameLevel class and if I want a property with default value I'll just call GameLevelWithDefaultValue
public abstract class GameLevel
{
public abstract int nextLevelToUnlock { get; set; }
public abstract List<LevelDetails> levelDetails { get; set; }
}
class GameLevelWithDefaultValue : GameLevel
{
public override int nextLevelToUnlock { get; set; } = 1;
public override List<LevelDetails> levelDetails { get; set; } = new List<LevelDetails>()
{
new LevelDetails{levelIndex = 1, Stars = 0 },
new LevelDetails{levelIndex = 2, Stars = 0 },
new LevelDetails{levelIndex = 3, Stars = 0 }
};
}
public class LevelDetails
{
public int levelIndex { get; set; }
public int Stars { get; set; }
}
I meant something like this:
public class GameLevel
{
public int NextLevelToUnlock { get; set; }
public List<LevelDetails> LevelDetails { get; set; }
public GameLevel() { }
public GameLevel(int nextLevelToUnlock, List<LevelDetails> levelDetails)
{
NextLevelToUnlock = nextLevelToUnlock;
LevelDetails = levelDetails;
}
}
public class LevelDetails
{
public int LevelIndex { get; set; }
public int Stars { get; set; }
public LevelDetails(int levelIndex, int stars)
{
LevelIndex = levelIndex;
Stars = stars;
}
}
public static class GameLevelBuilder
{
public static GameLevel BuildGameLevelWithDefaultValue()
{
var defaultLevelDetail = new List<LevelDetails>()
{
new LevelDetails(1, 0),
new LevelDetails(2, 0),
new LevelDetails(3, 0)
};
return new GameLevel(1, defaultLevelDetail);
}
}
When you need the object with the default value, you'll let the GameLevelBuilder create the object for you, while when you need the object without passing the initial values, you'll use the parameterless constructor of GameLevel.
You cannot instantiate an abstract class. If you inherit an abstract class, you must override it's abstract properties. So, the value of nextLevelToUnlock and levelDetails depends on the child class.
Also, default value for class in C# is null, or the result of it's zero parameter constructor for value types. If you don't assign any value to a field, it will get it's default value.

C# Counting properties of Class with child/nested objects

I have the following construction of classes, here simplified as child classes of a 'mother' class called DataClass, which also contains one simple method:
public class DataClass
{
public int num { get; set; }
public string code { get; set; }
public PartClass part { get; set; }
public MemberClass member { get; set; }
public int Count()
{
Type t = typeof(DataClass);
return typeof(DataClass).GetProperties().Length;
}
}
public class PartClass
{
public int seriesNum { get; set; }
public string seriesCode { get; set; }
}
public class MemberClass
{
public int versionNum { get; set; }
public SideClass side { get; set; }
}
public class SideClass
{
public string firstDetail { get; set; }
public string secondDetail { get; set; }
public bool include { get; set; }
}
The issue is, I want to refactor the method so that it can give me an accurate counting of all properties found, including the ones in nested or child classes. In the above example, it only counts properties of DataClass, while I wanted it to return 2 for DataClass + 2 for PartClass + 1 for MemberClass + 3 for SideClass, sums up to 8 properties you may set through DataClass.
Can someone help me with this?
You can introduce interface with Count() method
public interface ICountable
{
int Count();
}
And use this interface to mark all types, which properties are participating in Count() calculation.
You can see the generic abstract class to implement this interface below. Generic T parameter is type whose properties need to be calculated. You implement a calculation logic only once and inherit this class where needed. You also go through all of properties, implementing ICountable, to calculate them as well (some kind of recursion)
public abstract class Countable<T> : ICountable
{
public int Count()
{
Type t = typeof(T);
var properties = t.GetProperties();
var countable = properties.Select(p => p.PropertyType).Where(p => typeof(ICountable).IsAssignableFrom(p));
var sum = countable.Sum(c => c.GetProperties().Length);
return properties.Length + sum;
}
}
and inherit it in your classes
public class DataClass : Countable<DataClass>
{
...
}
public class PartClass : Countable<PartClass>
{
...
}
public class MemberClass : Countable<MemberClass>
{
...
}
public class SideClass : Countable<SideClass>
{
...
}
And this is for the test
var dataClass = new DataClass();
var count = dataClass.Count();
It returns 8 as expected

Use a value from a subclass in my main class if a property in main class is set to false

The sub class isn't derived from the main class, I'm just trying to differentiate them.
Even as I type this I can see it being impossible but I have some classes:
public class TransferServiceInformation {
public int ProviderId { get; set; }
public string PrePurchaseOverride { get; set; }
public bool PrePurchaseOverrideEnabled { get; set; }
}
and
public class TransferServiceProviderInformation {
public int ProviderId { get; set; }
public string PrePurchaseInfo { get; set; }
And I want it so that if I ever try to access myTransferServiceInformation.PrePurchaseOverride and PrePurchaseOverrideEnabled == false it should return PrePurchaseInfo from the TransferServiceProviderInformation with the same ID.
Is something like that even possible?
I'm just having a thought that a getter that requires a TransferServiceProviderInformation passed as an argument might work, and throw an exception if the IDs don't match. Is that the only solution? The thing is, I'd rather not have to dig through all the (thousands of lines of) code to change all the places were I (or someone else) has called this property.
This is just an idea:
Make a static list with instances inside your class and auto-fill it with using the constructor. Then you can check this list from outside for instances with the same id.
public class TransferServiceInformation
{
public int ProviderId { get; set; }
private string prePurchaseOverride;
public string PrePurchaseOverride
{
get
{
if(!PrePurchaseOverrideEnabled)
{
// Get instances from the other class where providerID matches
var instance = TransferServiceProviderInformation.Instances.Where(i => i.ProviderId == this.ProviderId).FirstOrDefault();
if(instance != null)
return (instance).PrePurchaseInfo;
}
return null; // If no match found
}
set
{
prePurchaseOverride = value;
}
}
private bool prePurchaseOverrideEnabled;
public bool PrePurchaseOverrideEnabled { get; set; }
}
public class TransferServiceProviderInformation
{
// Store your instances static
public static List<TransferServiceProviderInformation> Instances { get; set; }
public TransferServiceProviderInformation()
{
// Add every new instance to the list
Instances.Add(this);
}
public int ProviderId { get; set; }
public string PrePurchaseInfo { get; set; }
}
To-do's:
If an instance gets disposed, delete it from the list of instances.

Using a base class as parameter

I'm sure this is just a matter of me not understanding something completely obvious, but I seem to be hopefully stuck on this.
I have an abstract base class that is inherited by a large amount of other classes, to maintain security information across my application. I'll simplify for this question though.
public abstract class ModelBase
{
public int UserID { get; set; }
public string UserName { get; set; }
}
public class SpecificModel : ModelBase
{
public int specificInt { get; set; }
public string specificString { get; set; }
}
In this case, about 30 different classes all inherit from ModelBase.
I would like to create a method that can accept any object who's class inherits from ModelBase. So I created something like this:
public bool TestIt (ref ModelBase BaseModel)
{
BaseModel.UserID = 10;
BaseModel.UserName = "Evan";
return true;
}
However, if I try to pass in an object of type SpecificModel, I get an error.
SpecificModel hiThere = new SpecificModel();
hiThere.specificInt = 5;
hiThere.specificString = "Oh well";
bool retVal = TestMethods.TestIt(ref hiThere);
The error I see on the last line is: The best overloaded method match for 'TestMethods.TestIt(ref ModelBase)' has some invalid arguments
What am I not "getting" here?
Thanks
You have it right, except you don't want to be passing by ref (likely the source of your error). Your class is already a reference type, you probably don't need to pass a reference to it. Given the function definition in the question;
public bool TestIt (ModelBase BaseModel)
{
BaseModel.UserID = 10;
BaseModel.UserName = "Evan";
return true;
}
Will be perfect (except for the weird "always return true" but perhaps thats because this is demo code).
whats the error it throwing?
I have tried it myself its nothing look wrong in your code. might be your calling mechanism is not correct. here is the sample code.
class Program
{
static void Main(string[] args)
{
ModelBase sp = new SpecificModel2();
TestIt(ref sp);
}
public static bool TestIt(ref ModelBase BaseModel)
{
BaseModel.UserID = 10;
BaseModel.UserName = "Evan";
return true;
}
}
public abstract class ModelBase
{
public int UserID { get; set; }
public string UserName { get; set; }
}
public class SpecificModel : ModelBase
{
public int specificInt { get; set; }
public string specificString { get; set; }
}
public class SpecificModel2 : ModelBase
{
public int specificInt { get; set; }
public string specificString { get; set; }
}
}

ReadOnly Property C#

I want have readonly property in a Data Transfer Object,DTO object, without set; accessor like:
public class ViewBannerDTO
{
public int Id { get; }
}
but why get:
'ViewBannerDTO.Id.get' must declare a body because it is not marked abstract or extern. Automatically implemented properties must define both get and set accessors.
and also why i cant:
public readonly int Id{get;}
You can't have no setter for an auto-implemented property (otherwise how would you set it?). You can either add a getter implementation (and a backing field if necessary) or use a private setter:
public class ViewBannerDTO
{
public int Id { get; private set; }
}
Why i cant I do:
public readonly int Id{get;}
because readonly only applies to fields. You can accomplish the same thing with a property by using a readonly backing field and no set accessor:
private readonly int _Id;
public int Id {get { return _Id; } }
but you can't have a readonly auto-implement property because there's no syntax to initialize a property without a set accessor.
It is exactly what is sais: There is not set accessor for that variable and you have no Get method implemented which can do stuff to get you a value.
Either go:
public int Id { get; set; }
OR
public int Id
{
get
{
int something = GetStuffDone();
return something;
}
}
Another something you can do is make the set function private like this:
public int Id { get; private set; }
And an answer to why you cant: The value will never be set cause it has no accessor.
This is just a repeat of answers but OP does not understand
public class ViewBannerDTO
{
public int Id { get; private set; }
public ViewBannerDTO ()
{
Id = 12; // inside the class can assign private
// private not seen outside the classs
}
}
or you could
public class ViewBannerDTO
{
private int id = 12;
public int Id { get { return id; } }
}
or you could
public class ViewBannerDTO
{
public int Id { get { return 12; }
}
As of C# 9 you can get read-only behavior by using an init accessor. Example:
public class Foo
{
public int Bar { get; init;} = 1
public int Baz { get; private init;} = 2
}
var foo = new Foo { Baz = 3};
In both cases the property can only be set during object construction. The private keyword ensures only the class can set the value, otherwise the caller of new can set the value with the object literal notation in the example.
reference: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/init

Categories