Issue with using get keyword in C# relating to inheritance - c#

So I am having some issues with this. I am kinda new to C#. All my attributes are private and I am using the traditional get and set. It is an abstract class. But in the child class when I try and use it in another method, the compiler says cannot use as a method. However if I do the C++ way of accesors and mutators it works fine. Is there a way around this?
Thanks very much for your help
Never mind I got it. I have just been coding for like 7 hrs straight to get this assignment done for school and my brain isn't working right lol thanks very much though

This would be the standard C# way of doing what (I think) you're asking.
public abstract class Base
{
// Automatic Property
public string Prop1 { get; set; }
// With backing field
private string prop2;
public string Prop2
{
get { return prop2; }
set { prop2 = value; }
}
}
public class Derived : Base
{
public string Prop3 { get; set; }
}
public class AnotherClass
{
void Foo()
{
var derived = new Derived();
// Can get and set all properties
derived.Prop1 = derived.Prop1;
derived.Prop2 = derived.Prop2;
derived.Prop3 = derived.Prop3;
}
}

Related

inheritance, or should i use composition?

Lets say i have a class
public class Transfer
{
prop1
prop2
....
public List<SubTransfer> SubTransfers { get; set; }
}
Which i get from a function that connects to a database
Now i want to have a class that adds a status, both to the Transfer and to each one of the SubTransfer.
One question is if i should use inheritance here? or composition?
I think inheritance, so im trying to do something like this:
public ExtendedSubTransfer : SubTransfer
{
public StatusEnum Status { get; set; }
}
public ExtendedTransfer : Transfer
{
public StatusEnum Status { get; set;}
}
My problem is i dont know how to do that ill get a list of ExtendedSubTransfer when using ExtendedTransfer.
I know i can override SubTransfers using the keyword new like this:
public new List<ExtendedSubTransfers> SubTransfers {get; set;}
Is it "legit"? Or do you have other suggestions?
Thanks for the help!
It will compile but it probably isn't going to do what you want. Keep in mind that List<ExtendedSubTransfer> does not extend List<SubTransfer>. For example, if you have any operation that uses the base class you will not get what you want. To demonstrate, let us pretend the base class has an ID and you want to print the IDs.
public void PrintIds()
{
ExtendedTransfer extendedTransfer = _database.GetExtendedTransfer(...);
PrintSubTransferIds(extendedTransfer);
}
private PrintSubTransferIds(Transfer transfer)
{
foreach(var subTransfer in transfer.SubTransfers)
{
Console.WriteLine(subTransfer.Id);
}
}
The above method will not work unless you do something very strange when loading the items from the database. For example, if your loading code looks like...
public GetExtendedTransfer(...)
{
ExtendedTransfer result = new ExtendedTransfer();
List<ExtendedSubTransfer> subTransfers = _connection.QueryForSubTransfers(...);
result.SubTransfers = subTransfers;
return result;
}
Then it will not work. It will not print any subtransfer ids because transfer.SubTransfers will be an empty list. Instead you'd have to do something weird when loading from the database like...
public GetExtendedTransfer(...)
{
ExtendedTransfer result = new ExtendedTransfer();
List<ExtendedSubTransfer> subTransfers = _connection.QueryForSubTransfers(...);
result.SubTransfers = subTransfers;
Transfer subtypedResult = result;
subtypedResult.SubTransfers = subTransfers.Cast<SubTransfer>();
return result;
}
Also, the following case would be a compile time error:
public void PrintIds()
{
ExtendedTransfer extendedTransfer = _database.GetExtendedTransfer(...);
PrintSubTransferIds(extendedTransfer.SubTransfers);
}
private PrintSubTransferIds(List<SubTransfer> subTransfers)
{
foreach(var subTransfer in subTransfers)
{
Console.WriteLine(subTransfer.Id);
}
}
This would fail to compile because extendedTransfer.SubTransfers is of type List<ExtendedSubTransfer> which cannot be assigned to List<SubTransfer>.
Update: So what should you do?
C# (4.X and above) allows covariance on certain interfaces such as IReadOnlyList (C# 4.5 and above). Thus you can do...
public class Transfer
{
public virtual IReadOnlyList<SubTransfer> SubTransfers { get; private set; }
public void SetSubTransfers(List<SubTransfer> subTransfers)
{
SubTransfers = subTransfers;
}
}
public class ExtendedTransfer
{
private List<ExtendedSubTransfer> _subTransfers;
public override IReadOnlyList<SubTransfer> SubTransfers
{
get { return _subTransfers; }
}
public void SetSubTransfers(List<ExtendedSubTransfer> subTransfers)
{
_subTransfers = subTransfers;
}
}
This would be my best attempt at solving your problem. However, you didn't mention how you are getting your entities from the database. I don't think EntityFramework would be very happy with this field arrangement by default.

Something weird seems to have happened with C# classes

I used to be able to do this:
public class Something
{
public class SomethingElse
{
public static class ThisThing
{
public static string aoidj {get;set;}
}
}
}
But it no longer works.
My desired result (and what I've always been able to do) is:
Something.SomethingElse somethingElse = new Something.SomethingElse();
somethingElse.ThisThing.aoidj = "yay";
Console.WriteLine(somethingElse.ThisThing.aoidj);
But that no longer works. Instead of being able to access ThisThing from somethingElse, it's now appearing in SomethingElse.!
Has the C# language changed or something? The behaviour is definitely different and I don't know when it changed.
You need to do this:
Something.SomethingElse.ThisThing.aoidj = "yay";
Console.WriteLine(Something.SomethingElse.ThisThing.aoidj);
Or otherwise change your code to this:
public class Something
{
public class SomethingElse
{
public Whatever ThisThing = new Whatever();
public class Whatever
{
public string aoidj {get;set;}
}
}
}
And then you could do this (your desired result):
Something.SomethingElse somethingElse = new Something.SomethingElse();
somethingElse.ThisThing.aoidj = "yay";
Console.WriteLine(somethingElse.ThisThing.aoidj);
It has to appear in the SomethingElse., otherwise, how can you acces it, it is a Nested Type!
C# has not changed in this way. Nested Types have always been accessible through their parent types.
See my answer here: Cannot access nested classes or members of base class.
Besides, there is no point in having static classes as a Nested Type, since static classes are more commonly used as managers or providers, so they are mainly used elsewhere in your system.
Aside, if you want to access your static class members, you have to type in its name and access it once and for all.
Something.SomethingElse.ThisThing.aoidj
But I can't do that. It would be bad. I need to do it from somethingElse. Not SomethingElse.
Than make it a property rather than a class.
public class Something {
public class SomethingElse {
public OrEventSomethingElse ThisThing { get; set; }
}
}
public class OrEventSomethingElse {
public string aoidj { get; set; }
}
This way, you shall not be able to access it through your Nested Type SomethingElse, but rather through only an instance.
Some resources to help you understand OOP.
Object-Oriented Programming (C# and Visual Basic)
C# Tutorial - An Object Oriented Approach to Programming
Introduction to C# classes
C#.Net Tutorial 17-1 - Classes and Object-Oriented Programming (Part 1)
.NET Tutorial : Object Oriented Programming Using C# For Beginners - Part 1 - Introduction
Beginning C# Object-Oriented Programming
Object Oriented Programming using C# (DOWNLOAD FREE)
** I need it to be a class though, because there is more stuff to go inside of ThisThing**
Make it a class outside of SomethingElse so that you may access it as a simple instance member/property.
public class ThisThing {
public string Stuff { get; set; }
public int SomeMoreStuff { get; set; }
public DateTime EvenMoreStuff { get; set; }
// ...
public string ThisClassIsGettingHuge {
get {
return "Time to refactor because big classes tend to break SRP";
}
}
}
public class Something {
public class SomethingElse {
public ThisThing ThisThingAsAProperty { get; set; }
}
}
It is then, and only then that you shall only be able to access your instance.
var somethingElse = new Something.SomethingElse;
Console.WriteLine(somethingElse.ThisThingAsAProperty.ThisClassIsGettingHuge);
I have developed information and process for years, and I rarely use Nested Types. They generally cause more damage than they help.
Nothing is changed, but your code is wrong. And luckily I found answer too.
class Something
{
public class SomethingElse
{
public SomethingElse()
{
}
public static class sm
{
public static void set()
{
}
}
}
}
Use the class in this manner-
Something.SomethingElse.sm.set();

Generic Interface type conversion issues

I have been battling with this bit of code for a while now and I am trying to get a solution as it is literally the last part before it goes to testing.
I have the following interfaces and classes (simplified to the relevant parts):
public interface ITagParent<T> where T : ITag
{
List<TagAddOn<T>> TagCollection { get; set; }
}
public interface ITag
{
int Id { get; set; }
string Description { get; set; }
TagGroup TagGroup { get; set; }
}
public class TagAddOn<T> : ViewModelBase where T : ITag
{
private T _currentTag;
public T CurrentTag
{
get { return _currentTag; }
set { _currentTag = value; }
}
}
public partial class Customer : ITagParent<CustomerTag>
{
List<TagAddOn<CustomerTag>> _tagCollection;
public List<TagAddOn<CustomerTag>> TagCollection
{
get { return _tagCollection; }
set { _tagCollection = value; }
}
}
public partial class CustomerTag : ITag
{
public int Id { get; set; }
}
public class TagAddOnManager
{
public static string GetTagCurrentValue(List<TagAddOn<ITag>> dataObjectAddOns)
{
// LOTS OF SNIPPING!
return string.Empty;
}
}
I am trying to use the GetTagCurrentValue method in the TagAddOnManager class like this:
string value = TagAddOnManager.GetTagCurrentValue(
((ITagParent<ITag>)gridCell.Row.Data).TagCollection));
Everything compiles fine, but errors when trying to cast gridCell.Row.Data to ITagParent<ITag>. I understand this is due to covarience and a workaround (if not a terribly safe one) is to mark T in the ITagParent interface with the out keyword, but that won't work as you can see it is used in the TagCollection property, which can't be read only.
I tried casting the above to ITagParent<CustomerTag>, but this fails at compile time with a 'cannot convert' error when trying to feed it into my GetTagCurrentValue method.
Another option I considered is using some base classes instead of the ITagParent interface, but that won't work as the Customer object already inherits from another base class, which can't be modified for this implementation.
I know I could just overload the GetTagCurrentValue method with List<TagAddOn<CustomerTag>> as the parameter type and all other variations, but that really seems like a 'I give up' solution. I could probably use reflection to get the desired results, but that would be unwieldy and not very efficient, especially considering this method could be called a lot in a particular process.
So does anyone have any suggestions?
Could you use something like that
public class TagAddOnManager
{
public static string GetTagCurrentValue<TTag>(ITagParent<TTag> tagParent)
where TTag : ITag
{
// Just an example.
return tagParent.TagCollection.First().CurrentTag.Description;
}
}
and use it like that?`
var value = TagAddOnManager.GetTagCurrentValue((Customer)CustomergridCell.Row.Data);

C# new class clears base class values

I've searched extensively (though might have missed it). I've been doing so much web development that I can't seem to get this. I have a base case:
public class myfields
{
public String myfield1 { get; set; }
}
Then another class using this class:
class mydohere : myfields
{
public Boolean getValue {string xyz)
{
string abc = myfield1;
}
}
What I can't get it is, if I create:
mydohere Objmydohere = new mydohere();
The value of myfield1 is now null! All the values in base myfields are set to null (or empty since it is a new object). What is the best way to create fields (or parameters) in one class and share it among others without resetting their values? I've tried using keyword 'base'. I've tried using props and fields *since you can't instantiate them).
My goal is to to have a class of settable fields that I can use accross classes without making that class new for each class that is using it. Does this make sense? I'm sure there is a much better way to do this :)
It sounds like what you're looking for is a constant or static variable.
Use constant if it will always be the same:
const string myfield1 = "my const";
Use static if you'd like to set it once, maybe after doing some logic:
static string myfield1 = "my static";
This really depends on what you want to do with this "shared data" One way is to use a static class and dependency injection:
public interface Imyfields
{
String myfield1 { get; set; }
}
public class myfields : Imyfields
{
private static readonly Imyfields instance = new myfields();
private myfields()
{
}
public static Imyfields Instance
{
get
{
return instance;
}
}
public String myfield1 { get; set; }
}
class mydohere
{
private readonly Imyfields myfields;
public mydohere(Imyfields myfields)
{
this.myfields = myfields;
}
public Boolean getValue(string xyz)
{
string abc = this.myfields.myfield1;
}
}
Nothing is reset to null, it's never initialized with a value in the first time. In your base object, you only have a getter/setter, you don't have any code that initialize the value itself.
Maybe I don't understand the question well and others suggestion with static are what you really need! :)

Class inheritance & constructors

Hello to all the brilliant minds of StackOverflow!
I am getting familiar with c# class inheritance and multiple constructors but I can't seem to word a question that would allow me to Google it.
Here's what I have:
public class Order: OtherOrder
{
private OtherOrderManager _om;
public Order()
{
if (_om == null)
_om = new OtherOrderManager();
}
public Order(int orderID)
: base()
{
}
}
So obviously, now I can do something like:
Order order = new Order();
order.Member_From_OtherOrder_Class = "bleh";
But here's what I'm trying to implement in a constructor:
public class Order: OtherOrder
{
private OtherOrderManager _om;
public Order()
{
if (_om == null)
_om = new OtherOrderManager();
}
public Order(int orderID)
: base()
{
this = (Order)_om.GetOrder(orderID); //Returns an instance of OtherOrder
//Basically, I want to populate all the members of Order() interited
//from OtherOrder and fill them with data returned by this call.
}
}
Obviously, "this" is read only so that doesn't even compile. Is there any technical expression that would describe what I'm looking for ? Is it even possible ?
Thanks!
EDIT: I think I'll use reflection to loop through all members and get/set values this way.
Even though it's a bit vague about what you're trying to achieve, I'm guessing you might want to use something along the lines of using a factory possibly with copy-constructors. Essentially, the copy-constructors provide an easy means to populate data along the inheritance chain with your copies.
Consider the following base class:
public abstract class OrderBase
{
public int OrderID { get; private set; }
public string Name { get; protected set; }
public OrderBase()
{
}
public OrderBase(OrderBase copiedOrder)
{
this.OrderID = copiedOrder.OrderID;
this.Name = copiedOrder.Name;
}
}
(I left the parameterless constructor in there because I'm guessing it will be needed somewhere)
So an OrderBase can be instantiated by passing another OrderBase instance. Within that constructor, we know which properties to copy over and are compile-time checked.
Now a subclass might be:
public class CustomOrder : OrderBase
{
public Guid CustomID { get; private set; }
public CustomOrder()
{
}
public CustomOrder(CustomOrder copiedOrder)
: base(copiedOrder)
{
this.CustomID = copiedOrder.CustomID;
}
}
Here, the CustomOrder only copies its own property that is declared on it and passes the rest of the copying responsibility to the base class. Add one more class to the chain:
public class ValidatableCustomOrder : CustomOrder
{
public bool IsValid { get; private set; }
public ValidatableCustomOrder()
{
}
public ValidatableCustomOrder(ValidatableCustomOrder copiedOrder)
: base(copiedOrder)
{
this.IsValid = copiedOrder.IsValid;
}
}
And you can see how it can nicely manage each property set per subclass without any one class knowing much about the other. Your factory in turn might look something like:
public static class ValidatableCustomOrderLoader
{
public static ValidatableCustomOrder Get(int orderID)
{
ValidatableCustomOrder loadedOrder = LoadOrderFromSomewhere(orderID);
ValidatableCustomOrder copiedOrder = new ValidatableCustomOrder(loadedOrder);
return copiedOrder
}
private ValidatableCustomOrder LoadOrderFromSomewhere(int orderID)
{
//get your order somehow
}
}
So it (somehow) loads the data (perhaps from a database), copies it to a new instance which will chain through all the copy-constructors. Your calling code would look like:
int orderID = 10;
ValidatableCustomOrder order = ValidatableCustomOrderLoader.Get(orderID);
Anyhow, I can't say if this will specifically help you since your question/code seems a bit off-the-wall and vague, but hopefully it will help give you some ideas.
Two approaches come to mind: manually copy the properties:
public Order(int orderID)
: base()
{
var other = (Order)_om.GetOrder(orderID);
this.SomeProperty = other.SomeProperty; //repeat for each property/field that should be copied
}
Or use a static or factory method instead of constructors, e.g.:
public static Order GetOrder(int orderId)
{
return (Order)_om.GetOrder(orderID);
}
Try:
this._om = (Order)_om.GetOrder(orderID);
Hope that helps.

Categories

Resources