I have the following getter and setter method:
private Ansprechpartner partner;
public virtual Ansprechpartner Partner
{
get
{
if (partner == null)
{
// something like partner = " ";
}
return partner;
}
set
{
partner = value;
}
}
In the if clause i want to set partner = " ". But of course this isn't working, cause partner is a Typ a the class Ansprechpartner.
Is there a way to do something equivalent, so that partner returns an empty string if (partner == null)?
Please help
is Ansprechpartner your own class?
If it is, than you can return your own defenition of an "empty" Ansprechpartner
return Ansprechpartner.Empty;
and then define the empty property
public class Ansprechpartner
{
public static Ansprechpartner Empty
{
get
{
//generate an empty Ansprechpartner and return it here
}
}
You could override the ToString method from the Ansprechpartner and use a flag attribute like this:
public override ToString()
{
if (FlagAtrribute == null) //Or if it is a string, you could String.IsNullOrEmpty(FlagAtrribute)
{
return "";
}
return FlagAtrribute.ToString();
}
And in your getter just return a new empty instance of the Ansprechpartner class
get
{
if (partner == null)
{
partner = new Ansprechpartner();
}
return partner;
}
And in your code, do something like this:
MyClass.Partner.ToString();
If you change your return type from Ansprechpartner to object you can return anything you would like that derives from object. But I would strongly disagree with taking this approach. If you will want to rethink you're entire approach.
Your property doesn't actually appear to be working with strings, in which case returning a string would be an error.
However, answering your question directly of how to return a string, try something like this:
get
{
if (partner == null)
return String.Empty;
else
return partner;
}
}
Or, better yet:
get
{
return partner ?? String.Empty;
}
you could do something like:
get
{
if (partner == null)
return new Ansprechpartner() {whatever = ""};
else
return partner;
}
In my opinion there is a straightforward way to get exacly what you ask, that is to ensure that it is syntactically correct the folloging:
get
{
if (partner == null)
{
return = "";
}
return partner;
}
The way is to provide an implicict cast operator for the class. Thanks to implicit cast operator, the String.Empty or "" can be automatically casted to Ansprechpartner type, then it is perfectly legal the sysntax you use for the getter.
but what is a implicict cast operator ?
You can even see the question: How do I provide custom cast support for my class? for more detail.
I preferred, however, directly test the code for your class: the code used to successfully test it is the following:
private Ansprechpartner partner;
public virtual Ansprechpartner Partner
{
get
{
// legal assignment thanks to **public static implicit operator Ansprechpartner(string s)**
return partner ?? String.Empty;
}
set
{
partner = value;
}
}
We also try to make the inverse: thanks to public static implicit operator string(Ansprechpartner a) we see that is possible to assign an Empty string to a Ansprechpartner instance variabile
public void test_method()
{
Ansprechpartner s = String.Empty;
}
In the Ansprechpartner class we define cast operators
class Ansprechpartner
{
public static implicit operator Ansprechpartner(string s) {
// put your conversion logic here
// .. i.e: you can simply pass string s to a Ansprechpartner constructor
Ansprechpartner a = new Ansprechpartner();
return a;
}
public static implicit operator string(Ansprechpartner a)
{
if (a == null)
return "";
else
return a.ToString();
}
public Ansprechpartner()
{
}
public override string ToString()
{
return Value;
}
}
That's it, leave a comment if something has not been explained.
Related
I use a framework which exposes an abstract class called Value. Through operator overloading, it's possible to assign almost anything to this class's objects, and it works like a charm:
Value a = "hello";
Value b = 1;
Value c = true;
Value d = 3.14;
(Note that this is the only way to create instances of Value. There are no public/protected ways to assign values to instances, other than the overloaded operators.)
Right now, I want to override the implicit operator Value(string input) function, so that it XML-sanitizes any string before assigning it.
I have tried inheriting this class and overriding the operator, but have not found a way to feed the sanitized string into the base class's operator function. The following obviously doesn't work:
public override static implicit operator XmlValue(string input)
{
string output = sanitize(input);
XmlValue rv = null;
((Value)rv) = output; // this is not possible
return rv;
}
Is there a way to achieve this? Or alternatively, am I perhaps overthinking the problem and is there a better solution for what I want to do? In any case, I'd like to avoid having to sanitize each and every string before assigning it to a Value; this would be way too error prone.
FYI: the Value class is part of the Cottle framework.
The important point is that you cannot "override" operators, because they are static. You can instead define a new operator in your derived class, then make the assignment using a variable of your derived type (so that the compiler knows that it needs to call the operator of the derived class).
Look at this example:
using System;
class Value {
public string StringValue {
get;
private set;
}
protected Value(string str) {
StringValue = str;
}
public static implicit operator Value(string input) {
return new Value(input);
}
}
class XmlValue : Value {
protected XmlValue(string str) : base(str) {
}
public static implicit operator XmlValue(string input) {
// using "ToUpperInvariant" instead of sanitize
return new XmlValue(input.ToUpperInvariant());
}
}
class Program {
static void Main(string[] args) {
Value v1 = "test";
Console.WriteLine(v1.StringValue); // "test"
XmlValue v2 = "test";
Console.WriteLine(v2.StringValue); // "TEST"
}
}
After checking your comment, I think that the example below is more related to the real situation you are facing.
However, as fun as this operators overloading might be, I think that in this case you should definitely opt for the simpler and more readable solution of sanitizing every input before assignment.
using System;
abstract class Value {
public string StringValue {
get;
protected set;
}
public static implicit operator Value(string input) {
return new StringValue(input);
}
}
class StringValue : Value {
public StringValue(string str) {
StringValue = str;
}
}
class Xml {
string _value;
public Xml(string value) {
_value = value;
}
public static implicit operator Xml(string input) {
return new Xml(input.ToUpperInvariant());
}
public static implicit operator Value(Xml xml) {
Value ret = xml._value;
return ret;
}
}
class Program {
static void Main(string[] args) {
// this works with the cast operators...
Value v1 = (Xml)"test";
Console.WriteLine(v1.StringValue); // "TEST"
// ...but I would definitely go for this:
Value v2 = sanitize("test");
}
}
I have a method that returns a type of object based on the given column (a database class). However, when I assign the object the compiler throws an error saying it cannot implicitly convert type of object to int. How can I convert it without casting?
It looks better as:
this.Id = datum["Id"];
But now I have to include a cast, which makes the code a bit less clean and harder to code:
this.Id = (int)datum["Id"];
Here's my code:
public object this[string name]
{
get
{
object result;
if (this.Dictionary.ContainsKey(name))
{
if (this.Dictionary[name] is DBNull)
{
result = null;
}
else if (this.Dictionary[name] is byte && Meta.IsBool(this.Table, name))
{
result = (byte)this.Dictionary[name] > 0;
}
else
{
result = this.Dictionary[name];
}
}
else
{
result = default(object);
}
return result;
}
set
{
if (value is DateTime)
{
if (Meta.IsDate(this.Table, name))
{
value = ((DateTime)value).ToString("yyyy-MM-dd");
}
else if (Meta.IsDateTime(this.Table, name))
{
value = ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss");
}
}
if (this.Dictionary.ContainsKey(name))
{
this.Dictionary[name] = value;
}
else
{
this.Dictionary.Add(name, value);
}
}
}
You could change your indexer signature to:
public dynamic this[string name]
That would then make the conversion dynamic at execution time.
Personally, I prefer the cast approach though. It makes it clear that this is something that can fail - that you're telling the compiler that you have information which isn't available to it.
As an aside, your code can be written rather more simply, taking advantage of Dictionary<,>.TryGetValue and the behaviour of the dictionary indexer for setting:
public object this[string name]
{
get
{
object result;
if (Dictionary.TryGetValue(name, out result))
{
if (result is DBNull)
{
result = null;
}
else if (result is byte && Meta.IsBool(this.Table, name))
{
result = (byte) result > 0;
}
}
return result;
}
set
{
// TODO: Byte/bool conversions?
if (value is DateTime)
{
// Note use of invariant culture here. You almost certainly
// want this, given the format you're using. Preferably,
// avoid the string conversions entirely, but...
DateTime dateTime = (DateTime) value;
if (Meta.IsDate(this.Table, name))
{
value = dateTime.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
}
else if (Meta.IsDateTime(this.Table, name))
{
value = dateTime.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
}
}
Dictionary[name] = value;
}
}
Use class Convert:
Convert.ToInt32(datum["Id"]);
If you didn't need to state in your code that you are casting from object to int, then the programming language would not be helping you avoid mistakes.
C# does have a feature where you can switch off static type checking for specific variables: make your indexer return dynamic:
public dynamic this[string name]
Then you'll be able to say:
int n = datum["Id"];
But the downside is that you won't find out if this is correct until runtime.
You can do an extension method.
Create a class like this.
public static class ExtensionMethods
{
public static int AsInt(this object obj)
{
return (int)obj; // add additional code checks here
}
}
Then in your actual code all you have to do is call the extension method like this.
this.Id = datum["Id"].AsInt();
I know this may look the same as the cast but it happens underneath the method call AsInt and your code is cleaner and easier to read since AsInt is fluent and definitive.
Assume the following code:
public class CC3
{
private string _field;
private bool _someFlag;
public string Property
{
get { return _field; }
}
public bool SomeFlag
{
get { return _someFlag; }
}
public void SetField()
{
_field = " foo ";
_someFlag = true;
}
public string Method()
{
Contract.Requires(SomeFlag);
return Property.Trim();
}
}
The static checker of Code Contracts complains about the return statement of Method:
Possibly calling a method on a null reference 'this.Property'
What do I have to do to enable the static checker to prove that Property can never be null if SomeFlag is true?
You can give the static analysis a helping hand using Contract.Assume:
public string Method()
{
Contract.Requires(SomeFlag);
Contract.Assume(Property != null);
return Property.Trim();
}
Or actually add the check as a Contract.Requires in its own right. After all, just because you can manually prove it to be true for now, you can't guarantee that will always be the case when the code gets modified. In fact, consider whether SomeFlag being true is actually a requirement at all. Perhaps this is a cleaner solution:
public string Method()
{
Contract.Requires(Property != null);
return Property.Trim();
}
The only way to prove that it is not null is to prove that it is not null. Ideally you could use an invariant if you would convert to auto properties. For this example you could rewrite the property to ensure that null is not a possible result:
public string Property
{
get {
Contract.Ensures(Contract.Result<string>() != null);
return _field ?? String.Empty;
}
}
I have a class named config with two string fields named key paramValue and parameterPath.
When I apply the ChooseType method of the class, the method has to return one variable paramValue in different types (Int or bool or String).
I implemented it as follow:
class ConfigValue
{
public string paramPath;
private string paramValue;
public enum RetType {RetInt, RetBool, RetString};
public T PolimorphProperty<T>(RetType how)
{
{
switch (how)
{
case RetType.RetInt:
return (dynamic)int.Parse(paramValue);
case RetType.RetBool:
return (dynamic)Boolean.Parse(paramValue);
case RetType.RetString:
return (T)(object)paramValue;
default:
throw new ArgumentException("RetType not supported", "how");
}
}
}
}
My question is how can i access to the PolimorphProperty method in ConfigValue class, to retrive for examlple paramValue Int type.
Having both T and RetType is redundant. It should be something like this:
class ConfigValue
{
public string paramPath;
private string paramValue;
public T PolimorphProperty<T>()
{
return (T)Convert.ChangeType(paramValue, typeof(T));
}
}
Call it like configValue.PolimorphProperty<int>().
Or if you need to implement the type conversion manually, you can do something like this:
class ConfigValue
{
public string paramPath;
private string paramValue;
public T PolimorphProperty<T>()
{
if (typeof(T) == typeof(MySpecialType))
return (T)(object)new MySpecialType(paramValue);
else
return (T)Convert.ChangeType(paramValue, typeof(T));
}
}
I think following code best matches what you want (i have tested it before writing here...)
public T PolimorphProperty<T>()
{
object tt = Convert.ChangeType(paramValue, typeof(T));
if (tt == null)
return default(T);
return (T) tt;
}
And you can call the code like this:
int ret = cv.PolimorphProperty<int>();
Notes:
You really do not need to pass anything in the param list to determine the type of the returned value.
Make sure you put try-catch wherever you are checking the appropraite type for your future usage.
Good Morning All,
I'm trying to use "Contains" to see if an object is within the collection. When I break I can see that the object is indeed part of the collection however "Contains" seems to be returning false indicating the item is not in the collection. Any idea what I'm doing wrong?
if(HttpContext.Current.Session["AutoPayTypes"] != null)
{
var autopays = HttpContext.Current.Session["AutoPayTypes"] as List<PaymentTypeInfo>;
char? coverageProductLine = null;
if(entityProps.ContainsKey("CoverageProductLine"))
{
coverageProductLine = (char?)entityProps["CoverageProductLine"];
}
var paymentTypeInfoRepository = new PaymentTypeInfoRepository();
var payType = paymentTypeInfoRepository.GetPaymentTypeInfo(paymentAdd.PayType,
coverageProductLine);
if (autopays != null && payType != null)
paymentAdd.DaysPaid = autopays.Contains(payType) ? null : paymentAdd.DaysPaid;
}
If the object is not in the collection the "DaysPaid" needs to be null. Any ideas?
***UPDATE
PaymentTypeInfo is a standard LinqToSql generated class. Equals nor GetHashCode has been overridden at this point. Here is it's source.
[Table(Name="dbo.S_OptPaymentType")]
public partial class PaymentTypeInfo
{
private string _PaymentId;
private string _PaymentCode;
private System.Nullable<char> _CoverageType;
private string _ActionCode;
private System.Nullable<char> _PaymentType;
private string _BenAction;
private System.Nullable<char> _BenPremDisFlag;
private string _APNextToLastAct;
private string _APLastAct;
public PaymentTypeInfo()
{
}
[Column(Storage="_PaymentId", DbType="Char(3) NOT NULL", CanBeNull=false)]
public string PaymentId
{
get
{
return this._PaymentId;
}
set
{
if ((this._PaymentId != value))
{
this._PaymentId = value;
}
}
}
[Column(Storage="_PaymentCode", DbType="Char(2) NOT NULL", CanBeNull=false)]
public string PaymentCode
{
get
{
return this._PaymentCode;
}
set
{
if ((this._PaymentCode != value))
{
this._PaymentCode = value;
}
}
}
[Column(Storage="_CoverageType", DbType="Char(1)")]
public System.Nullable<char> CoverageType
{
get
{
return this._CoverageType;
}
set
{
if ((this._CoverageType != value))
{
this._CoverageType = value;
}
}
}
[Column(Storage="_ActionCode", DbType="VarChar(3)")]
public string ActionCode
{
get
{
return this._ActionCode;
}
set
{
if ((this._ActionCode != value))
{
this._ActionCode = value;
}
}
}
[Column(Name="PaymentType", Storage="_PaymentType", DbType="Char(1)")]
public System.Nullable<char> PaymentType
{
get
{
return this._PaymentType;
}
set
{
if ((this._PaymentType != value))
{
this._PaymentType = value;
}
}
}
[Column(Storage="_BenAction", DbType="VarChar(3)")]
public string BenAction
{
get
{
return this._BenAction;
}
set
{
if ((this._BenAction != value))
{
this._BenAction = value;
}
}
}
[Column(Storage="_BenPremDisFlag", DbType="Char(1)")]
public System.Nullable<char> BenPremDisFlag
{
get
{
return this._BenPremDisFlag;
}
set
{
if ((this._BenPremDisFlag != value))
{
this._BenPremDisFlag = value;
}
}
}
[Column(Storage="_APNextToLastAct", DbType="VarChar(3)")]
public string APNextToLastAct
{
get
{
return this._APNextToLastAct;
}
set
{
if ((this._APNextToLastAct != value))
{
this._APNextToLastAct = value;
}
}
}
[Column(Storage="_APLastAct", DbType="VarChar(3)")]
public string APLastAct
{
get
{
return this._APLastAct;
}
set
{
if ((this._APLastAct != value))
{
this._APLastAct = value;
}
}
}
}
Thanks,
~ck in San Diego
EDIT: As Ahmad pointed out, your conditional operator usage is incorrect. However, you don't even need to use the conditional operator here, as one of the branches results in a no-op. Just use this:
if (autopays != null && payType != null && !autopays.Contains(payType))
{
paymentAdd.DaysPaid = null;
}
Original answer
You haven't shown any thing about PaymentTypeInfo - does it override Equals and GetHashCode appropriately? If not, the containment check will be performed using reference identity, and it's very unlikely that the reference in the session is the same as the reference in the repository.
Either make PaymentTypeInfo override Equals and GetHashCode, or pass an appropriate IEqualityComparer<PaymentTypeInfo> into the Contains method.
(As SLaks mentions in the comments, in this case GetHashCode won't actually get called - but you should always override both Equals and GetHashCode or neither of them; if you do override them, you should do so in a consistent manner.)
Unless payType overrides Equals or you specify an IEqualityComparer, Contains will compare by reference.
Your collection probably contains a different instance of the class which is logically equivalent.
It's possible you're running into an equality issue - Contains() uses the IEquatable.Equals method, so you might check to make sure that that's going to return true for separate instances of the PaymentTypeInfo class.
Every post so far has a valid point; depending on the type being used Contains may not suffice. I am addressing a different part of your question though:
If the object is not in the collection
the "DaysPaid" needs to be null. Any
ideas?
How about switching the order of your ternary operator values to match the above statement? Use this:
paymentAdd.DaysPaid = autopays.Contains(payType) ? paymentAdd.DaysPaid : null;
Instead of this:
paymentAdd.DaysPaid = autopays.Contains(payType) ? null : paymentAdd.DaysPaid;
If the statement evaluates to false the 2nd item will be used, so make it null. The structure is:
logic statement ? true : false
Can you post the source of the PaymentType class? I am fairly certain that this type does not provided value-based semantics so the Contains method is forced to resort to using identity equality (which is not giving you the results you want).
If this is the case you may be interested in these articles I wrote on this topic:
All types are not compared equally
All types are not compared equally (part 2)