Givin the following code:
internal interface IHasLegs
{
int NumberOfLegs { get; }
}
internal interface IHasName
{
string Name { get; set; }
}
class Person : IHasLegs, IHasName
{
public int NumberOfLegs => 2;
public string Name { get; set; }
public Person(string name)
{
Name = name;
}
}
class Program
{
static void ShowLegs(IHasLegs i)
{
Console.WriteLine($"Something has {i.NumberOfLegs} legs");
}
static void Main(string[] args)
{
Person p = new Person("Edith Piaf");
ShowLegs(p);
Console.ReadKey();
}
}
Is there a way of implementing ShowLegs so that it only accepts values that implement IHasLegs and IHasName, without having to declare a intermediate IHasLegsAndHasName: IHasLegs, IHasName ? Something like ShowLegs((IHasLegs, IHasName) i) {}.
static void ShowLegs<T>(T i) where T : IHasLegs, IHasName
{
Console.WriteLine($"{i.Name} has {i.NumberOfLegs} legs");
}
Related
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ex1
{
internal class Program
{
static void Main(string[] args)
{
createCity("ex", 1, "ex1");
Console.ReadKey();
}
public void createCity(string name, int showOrder, string objectName)
{
City myObj = new City(name, showOrder);
}
}
}
using System;
public class City
{
public City()
{
string name;
static int code = 1;
int showOrder;
City(string name, int showOrder)
{
this.name = name;
this.showOrder = showOrder;
this.code++;
}
}
}
Any idea why? new to C#.
It doesn't know why the class City is, I don't understand why. I created it in the same project with the add option.
I'm just trying to create a new object of the class in the main.
create a constructor like this:
public City()
{
}
or with parameters:
public City(string name, int showOrder)
{
...
}
define the properties or fields of your class outside of the constructor
public class City
{
private string name { get; set; }
private int code { get; set; } = 1;
private int showOrder { get; set; }
}
Your 'code' property / field should not be static. This is causing an error in your constructor
int code = 1;
the reason you can't do createCity() inside the main method is because it is marked as static. Removing the static keyword should work.
private void Main(string[] args)
{
createCity("ex", 1, "ex1");
Console.ReadKey();
}
However you need a static void Main(string[] args) method in a console app, so I made createCity static as well
Full working example:
namespace ex1
{
public class Program
{
private static void Main(string[] args)
{
createCity("ex", 1, "ex1");
Console.ReadKey();
}
public static void createCity(string name, int showOrder, string objectName)
{
City myObj = new City(name, showOrder);
}
}
}
public class City
{
public City()
{
}
private string name { get; set; }
private int code { get; set; } = 1;
private int showOrder { get; set; }
public City(string name, int showOrder)
{
this.name = name;
this.showOrder = showOrder;
this.code++;
}
}
There are many things to fix:
static: Please make sure you understand this concept
This applies to:
static void createCity
code++;
The City class has multiple constructors and the class variable was defined in the wrong place.
You have to set the constructor public or at least internal:
public City(string name, int showOrder)
Corrected code:
Program.cs:
using System;
namespace ex1
{
internal class Program
{
static void Main(string[] args)
{
createCity("ex", 1, "ex1");
Console.ReadKey();
}
public static void createCity(string name, int showOrder, string objectName)
{
City myObj = new City(name, showOrder);
}
}
}
City.cs:
namespace ex1
{
public class City
{
string name;
static int code = 1;
int showOrder;
public City()
{
}
public City(string name, int showOrder)
{
this.name = name;
this.showOrder = showOrder;
code++;
}
}
}
Please try this following code :
using System;
namespace ex1
{
internal class Program
{
static void Main(string[] args)
{
City c = createCity("ex", 1, "ex1");
Console.WriteLine(c.ToString());
Console.ReadLine();
}
public static City createCity(string name, int showOrder, string objectName)
{
return new City(name, showOrder);
}
}
public class City
{
private string name;
private int code = 1;
private int showOrder;
public City(string name, int showOrder)
{
this.name = name;
this.showOrder = showOrder;
this.code++;
}
public override string ToString() => $"name: {name}; code:{code}; showOrder: {showOrder}";
}
}
I would like to create a method that can return the generic type defined in the class, here is a detailed example;
https://dotnetfiddle.net/SApVp3
using System;
public class Program
{
public static void Main()
{
// This would be some string imported from a CSV file
var customerData = "Customer,1,Ford";
var personData = "Person,675,Henry,Ford";
var customerImporter = new ImportData<CompanyMaster>();
customerImporter.ImportDataFromFile(customerData);
var personImporter = new ImportData<PersonMaster>();
personImporter.ImportDataFromFile(personData);
}
}
public class GenericRepository<TBase>
where TBase : EntityBase
{
public void Insert(TBase entity)
{
//.. generic Insert to database
}
}
public class ImportData<TBase>
where TBase : EntityBase
{
GenericRepository<TBase> _genericRepository;
//ctor
public void ImportDataFromFile(string data)
{
// convert the string data to TBase
_genericRepository = new GenericRepository<TBase>();
}
}
public class CsvConverter<TBase> where TBase: EntityBase{
public TBase ConvertTo(string someString)
{
if (someString.StartsWith("Customer"))
{
return GetCompany(someString);
}
else return GetPerson(someString);
}
private CompanyMaster GetCompany(string companyString){
return new CompanyMaster();
}
private PersonMaster GetPerson(string companyString){
return new PersonMaster();
}
}
public abstract class EntityBase
{
public int Id { get; set; }
public DateTime CreatedDate { get; set; }
}
public class CompanyMaster : EntityBase
{
public string CompanyName { get; set; }
}
public class PersonMaster : EntityBase
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
This currently throws;
Compilation error (line 47, col 11): Cannot implicitly convert type 'CompanyMaster' to 'TBase'
Compilation error (line 50, col 15): Cannot implicitly convert type 'PersonMaster' to 'TBase'
Can this be made to work?
You need to do an upcast using:
public TBase ConvertTo(string someString)
{
if ( someString.StartsWith("Customer") )
{
return (TBase)Convert.ChangeType(GetCompany(someString), typeof(TBase));
}
else
{
return (TBase)Convert.ChangeType(GetPerson(someString), typeof(TBase));
}
}
Or as suggested by #canton7:
if ( someString.StartsWith("Customer") )
{
return (TBase)(object)GetCompany(someString);
}
else
{
return (TBase)(object)GetPerson(someString);
}
Difference between casting and using the Convert.To() method
I'm trying to inherit a method that returns a Generic BindingList of type ServerType. For example, let's say I have the following:
public interface IServer
{
string IpAddress { get; set; }
string Name { get; set; }
string HostName { get; set; }
string OsVersion { get; set; }
}
public class BaseServer : IServer
{
private string _IpAddress;
private string _Name;
private string _HostName;
private string _OsVersion;
public string IpAddress
{
get { return _IpAddress; }
set { _IpAddress = value; }
}
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public string HostName
{
get { return _HostName; }
set { _HostName = value; }
}
public string OsVersion
{
get { return _OsVersion; }
set { _OsVersion = value; }
}
}
public class ServerTypeA : BaseServer { }
public class ServerTypeB : BaseServer { }
public class ServerTypeC : BaseServer { }
public class ServerTypeList : List<ServerTypeA>
{
public BindingList<ServerTypeA> ToBindingList()
{
BindingList<ServerTypeA> myBindingList = new BindingList<ServerTypeA>();
foreach (ServerTypeA item in this.ToList<ServerTypeA>())
{
_bl.Add(item);
}
return _bl;
}
}
Is there any way I can do the "ToBindingList" method without having to repeat it in each derived server class and have it use the correct generic type.
First offf donĀ“t derive from List<T>. Instead use it (favor composition over inheritance).
Then make your Repositories-class generic:
public class Repository : Server
{
}
public class Repositories<T> where T: Server
{
private List<T> theList = new List<T>();
public Repositories<T>(List<T> theList) this.theList = theList; }
public BindingList<T> ToBindingList()
{
BindingList<T> myBindingList = new BindingList<T>();
foreach (Titem in this.theList)
{
_bl.Add(item);
}
return _bl;
}
}
Now you can have Repositories-instances of arbitrary classes deriving from Server.
First, create a base list for all your collections:
public class MyListBase<T> : List<T>
where T: Server
{
public BindingList<T> ToBindingList()
{
BindingList<T> myBindingList = new BindingList<T>();
foreach (T item in this.ToList<T>())
myBindingList.Add(item);
return myBindingList;
}
}
Then use this one to inherit from:
public class Repositories : MyListBase<Repository>
{
}
I have a pretty simple and straightforward question.
What is the standardized way, or the right way, of calling another constructor of a class, along with the base constructor of such class?
I understand that the second example does not work. It just seems hackish to be doing it the third way. So what is the way that the people who designed C# expected users to do this?
For example:
public class Person
{
private int _id;
private string _name;
public Person()
{
_id = 0;
}
public Person(string name)
{
_name = name;
}
}
// Example 1
public class Engineer : Person
{
private int _numOfProblems;
public Engineer() : base()
{
_numOfProblems = 0;
}
public Engineer(string name) : this(), base(name)
{
}
}
// Example 2
public class Engineer : Person
{
private int _numOfProblems;
public Engineer() : base()
{
InitializeEngineer();
}
public Engineer(string name) : base(name)
{
InitializeEngineer();
}
private void InitializeEngineer()
{
_numOfProblems = 0;
}
}
Can't you simplify your approach by using an optional parameter?
public class Person
{
public int Id { get; protected set; }
public string Name { get; protected set; }
public Person(string name = "")
{
Id = 8;
Name = name;
}
}
public class Engineer : Person
{
public int Problems { get; private set; }
public Engineer(string name = "")
: base(name)
{
Problems = 88;
}
}
[TestFixture]
public class EngineerFixture
{
[Test]
public void Ctor_SetsProperties_AsSpecified()
{
var e = new Engineer("bogus");
Assert.AreEqual("bogus", e.Name);
Assert.AreEqual(88, e.Problems);
Assert.AreEqual(8, e.Id);
}
}
Imagine a class as follows.. It's a class provided to me to work with.. I cannot change its source..
public class MyClass
{
object _Object { get; set; }
public void FuncA1() { _Object = new object(); }
public void FuncA2() { _Object = new List<object>(); }
public int FuncB1() { _Object = 0; return 0; }
public int FuncB2() { _Object = 123; return 123; }
public string FuncC1() { _Object = null; return null; }
public string FuncC2() { _Object = "Hello"; return "Hello"; }
}
Im trying to create a wrapper for this class, such that I can group its many functions into categories..
MyWrapper.Voids.FuncA1();
MyWrapper.Voids.FuncA2();
MyWrapper.Integers.FuncB1();
MyWrapper.Integers.FuncB2();
MyWrapper.Strings.FuncC1();
MyWrapper.Strings.FuncC2();
The only solution I can think of for this scenario is to design the wrapper like this:
public class MyWrapper
{
MyClass _Instance { get; set; }
public _Void Voids { get; private set; }
public _Integer Integers { get; private set; }
public _String Strings { get; private set; }
public class _Void
{
MyWrapper _Parent { get; set; }
public void FuncA1() { _Parent._Instance.FuncA1(); }
public int FuncA2() { return _Parent._Instance.FuncA2(); }
}
public class _Integer
{
...
}
public class _String
{
...
}
public MyWrapper()
{
_Instance = new MyClass();
Voids = new _Voids(this);
Integers = new _Integer(this);
Strings = new _String(this);
}
}
This solution works, but has a number of problems:
- The inner classes are forced to be public, which allows them to be instantiated by the user..
- I am forced to maintain a reference of the parent object in the child classes..
Is there a better way of doing this?
EDIT: The code posted initially was a bit confusing, in the sense that it was diverting attention away from the core issue and more into the issues of whether a function would cause exceptions or not if they all work on the same object..
NOTE: This is not actual code.. I hacked together this example to show what I'm trying to do.. CREATE A WRAPPER AROUND AN OBJECT (I cannot change the original object's code) AND GROUP FUNCTIONS INTO CATEGORIES..
FINAL EDIT: following suggestion by Juharr.. here's what ive done to accomplish what i wanted.. for the betterment of others..
public interface IVoid
{
void FuncA1();
void FuncA2();
}
public interface IInteger
{
int FuncB1();
int FuncB2();
}
public class MyWrapper
{
public MyClass Instance { get; private set; }
public IVoid Voids { get; private set; }
public IInteger Integers { get; private set; }
private abstract class MyBase
{
protected MyWrapper Parent { get; set; }
protected MyClass Instance { get { return Parent.Instance; } }
public MyBase(MyWrapper oParent) { Parent = oParent; }
}
private class MyVoid : MyBase, IVoid
{
public MyVoids (MyWrapper oParent) : base(oParent) { }
public void FuncA1() { Instance.FuncA1(); }
public void FuncA2() { Instance.FuncA2(); }
}
private class MyInteger : MyBase, IInteger
{
public MyInteger (MyWrapper oParent) : base(oParent) { }
public int FuncB1() { return Instance.FuncB1(); }
public int FuncB2() { return Instance.FuncB2(); }
}
public MyWrapper()
{
Instance = new MyClass();
Voids = new MyVoid(this);
Integers = new MyInteger(this);
}
}
You could write public interfaces instead. Then your inner classes don't have to be public. So something like this.
public interface IIntger
{
void Set(int iValue);
int Get();
}
public class MyWrapper
{
MyClass _Instance { get; set; }
public IInteger Integer { get; private set; }
private class _Integer : IInteger
{
MyWrapper _Parent { get; set; }
public void Set(int iValue) { _Parent._Instance.IntegerSet(iValue); }
public int Get() { return _Parent._Instance.IntegerGet(); }
}
public MyWrapper()
{
_Instance = new MyClass();
Integer = new _Integer(this);
}
}
EDIT:
To answer the second part of your question you will either need the reference to the parent class or a reference to the class you are wrapping. So you could have this instead.
public class MyWrapper
{
public IInteger Integer { get; private set; }
private class _Integer : IInteger
{
MyClass _Instance { get; set; }
public _Integer(MyClass myClass) { _Instance = myClass; }
public void Set(int iValue) { _Instance.IntegerSet(iValue); }
public int Get() { return _Instance.IntegerGet(); }
}
public MyWrapper(MyClass instance)
{
Integer = new _Integer(instance);
}
}