Suppose class A as:
public class A
{
private string _str;
private int _int;
public A(string str)
{
this._str = str;
}
public A(int num)
{
this._int = num;
}
public int Num
{
get
{
return this._int;
}
}
public string Str
{
get
{
return this._str;
}
}
}
I want to hide Str property when i construct class A as
new A(2)
and want to hide Num property when i construct class A as
new A("car").
What should i do?
That isn't possible with a single class. An A is an A, and has the same properties - regardless of how it is constructed.
You could have 2 subclasses of abstract A, and a factory method...
public abstract class A
{
class A_Impl<T> : A
{
private T val;
public A_Impl(T val) { this.val = val; }
public T Value { get { return val; } }
}
public static A Create(int i) { return new A_Impl<int>(i); }
public static A Create(string str) { return new A_Impl<string>(str); }
}
But : the caller will not know about the value unless they cast it.
use generics
public class A<T>
{
private T _value;
public A(T value)
{
this._value= value;
}
public TValue
{
get
{
return this._value;
}
}
}
Related
Given the following code:
static class StaticClass
{
public static void DoSomething(BaseClass Value)
{
}
}
abstract class BaseClass
{
}
class DerivedClassForString : BaseClass
{
public string Value { get; }
public DerivedClassForString(string Value)
{
this.Value = Value;
}
public static implicit operator DerivedClassForString(string Value)
{
return new DerivedClassForString(Value);
}
}
class DerivedClassForInt32 : BaseClass
{
public int Value { get; }
public DerivedClassForInt32(int Value)
{
this.Value = Value;
}
public static implicit operator DerivedClassForInt32(int Value)
{
return new DerivedClassForInt32(Value);
}
}
I want to be able to do the following:
StaticClass.DoSomething("Hello world!"); //This should create an instance of DerivedClassForString
StaticClass.DoSomething(16); //This should create an instance of DerivedClassForInt32
This however does not work.
Is there any way to give the compiler a hint to go through the derived classes and search for the implicit resolver?
An other way of doing it would be defining the implicit conversions within BaseClass itself :
abstract class BaseClass
{
public static implicit operator BaseClass(string Value)
{
return new DerivedClassForString(Value);
}
public static implicit operator BaseClass(int Value)
{
return new DerivedClassForInt32(Value);
}
}
Depending on what StaticClass.DoSomething and BaseClass really does, you could make both BaseClass and StaticClass.DoSomething generic :
static class StaticClass
{
public static void DoSomething<T>(BaseClass<T> Value)
{
}
}
class BaseClass<T>
{
public T Value { get; }
public BaseClass(T Value)
{
this.Value = Value;
}
public static implicit operator BaseClass<T>(T Value)
{
return new BaseClass<T>(Value);
}
}
If you want the compiler to infer T when calling StaticClass.DoSomething you'll need to make DoSomething look like this though :
static class StaticClass
{
public static void DoSomething<T>(T Value)
{
BaseClass<T> realValue = Value;
}
}
If I have the following:
public abstract class Parameter<T>
{
protected T value;
public virtual T Value
{
get { return value; }
set { this.value = value; }
}
protected Parameter(T startingValue)
{
value = startingValue;
}
}
public class FloatParameter : Parameter<float>
{
public FloatParameter(float startingValue) : base(startingValue){}
}
public class IntParameter : Parameter<int>
{
public override int Value
{
get { return value; }
set { this.value = value > 100 ? 100 : value; }
}
public IntParameter(int startingValue) : base (startingValue) {}
}
Is there any way to create some List<Parameter> that can contain any of the derived types? For example, something like:
// no type specified in Parameter
List<Parameter> storedParameters = new List<Parameter>();
storedParameters.Add(new FloatParameter(2f));
storedParameters.Add(new IntParameter(7));
foreach(Parameter p in storedParameters)
{
DoSomethingWithValue(p.Value);
}
Or, alternatively, if this implementation is flawed, is there a better way to do this? What I have here feels slightly naive.
The only way I see to manage such case is to have and Interface that you use to manage the generic types, something like this should work:
public interface IParameter
{
void DoSomething();
}
public abstract class Parameter<T>
{
protected T value;
public T Value
{
get { return value; }
set { this.value = value; }
}
protected Parameter(T startingValue)
{
value = startingValue;
}
}
public class FloatParameter : Parameter<float>, IParameter
{
public FloatParameter(float startingValue) : base(startingValue) { }
public void DoSomething()
{
Console.WriteLine(value);
}
}
public class IntParameter : Parameter<int>, IParameter
{
public IntParameter(int startingValue) : base(startingValue) { }
public void DoSomething()
{
Console.WriteLine(value);
}
}
Ont his case you would be able to create a List of the Interface IParameter and add there specific instances:
var list = new List<IParameter>();
list.Add(new FloatParameter(1F));
list.Add(new IntParameter(1));
foreach (var item in list)
{
item.DoSomething();
}
Try to add nongeneric interface. Here is an example:
public class Program
{
static void Main(string[] args)
{
try
{
List<IParameter> storedParameters = new List<IParameter>();
storedParameters.Add(new FloatParameter(2f));
storedParameters.Add(new IntParameter(7));
foreach (IParameter p in storedParameters)
{
Console.WriteLine(p.ToString());
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
public interface IParameter
{
object value { get; }
}
public class Parameter<T> : IParameter
{
public object value { get; protected set; }
public virtual T Value
{
get { return (T)value; }
set { this.value = value; }
}
protected Parameter(T startingValue)
{
value = startingValue;
}
}
public class FloatParameter : Parameter<float>
{
public FloatParameter(float startingValue) : base(startingValue){ }
}
public class IntParameter : Parameter<int>
{
public override int Value
{
get { return (int)value; }
set { this.value = value > 100 ? 100 : value; }
}
public IntParameter(int startingValue) : base (startingValue) { }
}
No, it's not possible to do it.
What you are trying to do is to have an interface (or base class) that expose a property of an undefined type, to be able to then retrieve that value and dispatch it dynamically to the proper override of DoSomethingWithValue.
What you are after is achievable defining the property as dynamic, instead of using generics.
public class Parameter
{
protected dynamic value;
public dynamic Value
{
get { return value; }
set { this.value = value; }
}
public Parameter(dynamic startingValue)
{
value = startingValue;
}
}
public class MyStuff {
public void DoStuff()
{
List<Parameter> storedParameters = new List<Parameter>();
storedParameters.Add(new Parameter(2f));
storedParameters.Add(new Parameter(7));
foreach (Parameter p in storedParameters)
{
DoSomethingWithValue(p.Value);
}
}
}
Otherwise you should look into implementing a Double dispatch.
You can do it by defining a common interface and using the visitor pattern.
public interface IParameterVisitor
{
void VisitInt(int value);
void VisitFloat(float value);
}
public interface IParameter
{
void Accept(IParameterVisitor visitor);
}
The previous implementation has to be modified a bit:
public abstract class Parameter<T> : IParameter
{
protected T value;
public virtual T Value
{
get { return value; }
set { this.value = value; }
}
protected Parameter(T startingValue)
{
value = startingValue;
}
public abstract void Accept(IParameterVisitor visitor);
}
FloatParameter will VisitFloat, and IntParameter will VisitInt
public class FloatParameter : Parameter<float>
{
public FloatParameter(float startingValue) : base(startingValue) { }
public override void Accept(IParameterVisitor visitor)
{
visitor.VisitFloat(this.value);
}
}
public class IntParameter : Parameter<int>
{
public override int Value
{
get { return value; }
set { this.value = value > 100 ? 100 : value; }
}
public override void Accept(IParameterVisitor visitor)
{
visitor.VisitInt(this.value);
}
public IntParameter(int startingValue) : base(startingValue) { }
}
And our visitor for example:
public class MyVisitor : IParameterVisitor
{
public void VisitInt(int value)
{
Console.WriteLine($"Visiting an int: {value}");
}
public void VisitFloat(float value)
{
Console.WriteLine($"Visiting a float: {value}");
}
}
Finally, the usage:
var parameters =
new List<IParameter> {new FloatParameter(0.5f), new IntParameter(1)};
var visitor = new MyVisitor();
foreach (IParameter parameter in parameters) {
parameter.Accept(visitor);
}
If you change the value to an object you will be able to set the value to whatever type you like:
class Program
{
static void Main(string[] args)
{
// no type specified in Parameter
var storedParameters = new List<ParameterBase>();
storedParameters.Add(new FloatParameter(3.5F));
storedParameters.Add(new IntParameter(7));
foreach (var p in storedParameters)
{
Console.WriteLine(p.Value);
}
}
}
public class ParameterBase
{
protected object value;
public virtual object Value
{
get { return value; }
set { this.value = value; }
}
}
public class FloatParameter : ParameterBase
{
public FloatParameter(float value)
{
Value = value;
}
}
public class IntParameter : ParameterBase
{
public IntParameter(int value)
{
Value = value;
}
}
UPDATED: Use object instead of dynamic and removed ValueType as suggested by #Pieter Witvoet
In C#, when specifying how an attribute class should be used, there is a GenericParameter value in the System.AttributeTargets enum. How can we apply such an attribute, what is the syntax ?
[System.AttributeUsage(System.AttributeTargets
public sealed class MyAnnotationAttribute : System.Attribute {
public string Param { get; private set; }
public MyAnnotationAttribute(string param) { Param = param; }
}
Same question goes for other exotic attribute targets, like System.AttributeTargets.Module (I don't even know how to declare modules other than the main module???), System.AttributeTargets.Parameter and System.AttributeTargets.ReturnValue.
// Assembly and module
[assembly: AttributesTest.MyAnnotation("Assembly")]
[module: AttributesTest.MyAnnotation("Module")]
namespace AttributesTest
{
// The attribute
[System.AttributeUsage(System.AttributeTargets.All, AllowMultiple = true)]
public sealed class MyAnnotationAttribute : System.Attribute
{
public string Param { get; private set; }
public MyAnnotationAttribute(string param) { Param = param; }
}
// Types
[MyAnnotation("Class")]
public class SomeClass { }
[MyAnnotation("Delegate")]
public delegate int SomeDelegate(string s, float f);
[MyAnnotation("Enum")]
public enum SomeEnum { ValueOne, ValueTwo }
[MyAnnotation("Interface")]
public interface SomeInterface { }
[MyAnnotation("Struct")]
public struct SomeStruct { }
// Members
public class MethodsExample
{
[MyAnnotation("Constructor")]
public MethodsExample() { }
[MyAnnotation("Method")]
public int SomeMethod(short s) { return 42 + s; }
[MyAnnotation("Field")]
private int _someField;
[MyAnnotation("Property")]
public int SomeProperty {
[MyAnnotation("Method")] get { return _someField; }
[MyAnnotation("Method")] set { _someField = value; }
}
private SomeDelegate _backingField;
[MyAnnotation("Event")]
public event SomeDelegate SomeEvent {
[MyAnnotation("Method")] add { _backingField += value; }
[MyAnnotation("Method")] remove { _backingField -= value; }
}
}
// Parameters
public class ParametersExample<T1, [MyAnnotation("GenericParameter")]T2, T3>
{
public int SomeMethod([MyAnnotation("Parameter")]short s) { return 42 + s; }
}
// Return value
public class ReturnValueExample
{
[return: MyAnnotation("ReturnValue")]
public int SomeMethod(short s) {
return 42 + s;
}
}
}
I have the following code for supporting a list of different types :
public enum eType
{
tInt,
tString,
tDateTime
}
public interface ICustomType<out T>
{
T Value { get; }
}
public abstract class DifferentType
{
protected DifferentType(eType type, string mnemonic)
{
Type = type;
Mnemonic = mnemonic;
}
public string Mnemonic { get; private set; }
public eType Type { get; private set; }
}
public class DateTimeType : DifferentType, ICustomType<DateTime>
{
public DateTimeType(DateTime value, string mnemonic)
: base(eType.tDateTime, mnemonic)
{
Value = value;
}
public DateTime Value { get; private set; }
}
public class IntType : DifferentType, ICustomType<int>
{
public IntType(int value, string mnemonic)
: base(eType.tInt, mnemonic)
{
Value = value;
}
public int Value { get; private set; }
}
public class StringType : DifferentType, ICustomType<string>
{
public StringType(string value, string mnemonic)
: base(eType.tString, mnemonic)
{
Value = value;
}
public string Value { get; private set; }
}
public static class UtilValue
{
public static T GetValue<T>(DifferentType customType)
{
return ((ICustomType<T>)customType).Value;
}
}
public class testTypes2
{
public testTypes2()
{
var values = new List<DifferentType> { GetInt(), GetString(), GetDate() };
foreach (var i in values)
{
switch (i.Type)
{
case eType.tInt:
int resInt = UtilValue.GetValue<int>(i);
break;
case eType.tString:
string resString = UtilValue.GetValue<string>(i);
break;
case eType.tDateTime:
DateTime resDateTime = UtilValue.GetValue<DateTime>(i);
break;
}
}
}
private DateTimeType GetDate()
{
return new DateTimeType(new DateTime(2000, 1, 1), "MnemonicDate");
}
private IntType GetInt()
{
return new IntType(5, "MnemonicInt");
}
private StringType GetString()
{
return new StringType("ok", "MnemonicString");
}
}
and would like to avoid the cast at line return ((ICustomType<T>)customType).Value; in the UtilValue class, any idea how I can get rid of that while still keeping the design?
I am not even sure if this cast is expensive to do? My guess is most certainly.
Visitor-pattern example:
interface IDifferentTypeVisitor
{
void Visit(DateTimeType dt);
void Visit(StringType st);
}
class DifferentType
{
public abstract void Accept(IDifferentTypeVisitor visitor);
}
class DateTimeType : DifferentType
{
public void Accept(IDifferentTypeVisitor visitor)
{
visitor.Visit(this);
}
}
class StringType : DifferentType
{
public void Accept(IDifferentTypeVisitor visitor)
{
visitor.Visit(this);
}
}
class SomeVisitor : IDifferentTypeVisitor
{
public void Visit(DateTimeType dt)
{
//DateTime resDateTime = dt.Value; Or similar
}
public void Visit(StringType st)
{
//string resString = st.Value; Or similar
}
}
public class testTypes2
{
public testTypes2()
{
var values = new List<DifferentType> { /* Content */ };
var visitor = new SomeVisitor();
foreach (var i in values)
{
i.Accept(visitor);
}
}
}
In C# 4 with dynamic it's possible to save some code by adding this to DifferentType:
public void Accept(IDifferentTypeVisitor visitor)
{
visitor.Visit((dynamic)this);
}
and then delete all other Accept methods. It hurts performance but it looks better ;-)
I'm wondering about what's the way to go, if I need to publicate data-interfaces but want to use them internal with extended calculated properties. To make it clearer:
// The public interface
public interface IData
{
int Property { get; }
}
// The internal interface
internal interface IExtendedData : IData
{
int ExtendedProperty { get; }
}
// The assumed implementation of someone using my interface
public class Data : IData
{
public Data(int a)
{
Property = a;
}
public int Property
{
get;
private set;
}
public override string ToString()
{
return Property.ToString();
}
}
// My implementation
internal class ExtendedData : IExtendedData
{
public ExtendedData(int a)
{
Property = a;
}
public int Property
{
get;
private set;
}
public int ExtendedProperty
{
get
{
return 2 * Property;
}
}
public override string ToString()
{
return Property.ToString() + ExtendedProperty.ToString();
}
}
// publicated by me, for the person who uses my dll
public static class Calculations
{
public static int DoSomeCalculation(IData data, int parameter)
{
// This probably don't work, but maybe shows what I want to do
IExtendedData tempData = (ExtendedData)data;
return tempData.ExtendedProperty * parameter;
}
}
I'm realy frustrated, cause I feel like missing some basical programing skills.
You could solve this problem by implementing ExtendedData as a Wrapper for a class implementing IData
internal class ExtendedData : IExtendedData
{
private IData data;
public ExtendedData(IData data)
{
this.data = data;
}
public int Property
{
get { return data.Property; }
private set { data.Property = value; }
}
public int ExtendedProperty
{
get
{
return 2 * Property;
}
}
}
and use this in DoSomeCalculation like
IExtendedData tempData = new ExtendedData(data);
ExtendedData could inherit from Data:
class ExtendedData : Data
{...}
And for creation of a Data object you add a factory like so:
public class DataFactory
{
public IData CreateData()
{
return new ExtendedData();
}
}
User have to create all its Data objects by this factory. You can ensure it by making Data's constructor internal.
In your DLL you can then cast to ExtendedData.