I have a function with this signature:
public void DoSomething(String name);
The string name is special in my application. It can be either an arbitrary string, or a special known value. Because any non-empty string value is a valid input it means I need to use object reference equality with empty strings, like so:
public class Foo {
public const String SpecialValue1 = "";
public const String SpecialValue2 = "";
public void DoSomething(String name) {
if( Object.ReferenceEquals( name, SpecialValue1 ) ) {
} else if( Object.ReferenceEquals( name, SpecialValue2 ) {
} else {
}
}
public void UsageExample() {
DoSomething( SpecialValue1 );
DoSomething( "some arbitrary value" );
}
}
I want to know if this technique, using empty strings and object reference equality will always be safe, especially with respect to string interning.
Antimony is right about the reasons this will not work.
I would suggest that you define a type for the argument. Let's call it ExampleArgument.
public class ExampleArgument
{
private readonly int _knownValue;
private readonly string _arbitraryValue;
public ExampleArgument(string arbitraryValue)
{
_arbitraryValue = arbitraryValue;
_knownValue = 0;
}
private ExampleArgument(int knownValue)
{
_knownValue = knownValue;
_arbitraryValue = null;
}
public static readonly ExampleArgument FirstKnownValue = new ExampleArgument(1);
public static readonly ExampleArgument SecondKnownValue = new ExampleArgument(2);
// obvious Equals and GetHashCode overloads
// possibly other useful methods that depend on the application
}
Oh, and if you really want the calling syntax in your example, you could add:
public static implicit operator ExampleArgument(string arbitraryValue)
{
return new ExampleArgument(arbitraryValue);
}
Which is an implicit conversion operator from string to ExampleArgument.
DoSomething(ExampleArgument.FirstKnownValue);
DoSomething(new ExampleArgument("hello"));
DoSomething("hello"); // equivalent to previous line, uses implicit conversion operator
No, this is not safe. In fact, this will never work. String literals get interned, so both special values will have the same reference. Most compilers will also intern compile time constant strings, and you can always intern strings manually.
Unfortunately, if you want to accept any valid string, you need some other way to pass extra information. And even if a hack like this worked, it would be a bad idea, since it violates normal string equality semantics.
Here are the possibilities I can think of
If you only have one special value, you can use null
Take a broader type such as Object as input
Take two parameters
Make a separate function
Related
I have a class with predefined constant strings which are used as keys to retrieve the data from the external storage by provided key.
public class StorageKeys
{
public const string SomeKey = "Foo";
public const string AnotherKey = "Foooo";
}
public interface IStorage
{
string GetValue(string key);
}
Which is used like this:
IStorage t = new Storage();
string value = t.GetValue(StorageKeys.SomeKey);
It works but I'm concerned that potentiality it's possible to call GetValue method with just string argument which can cause an error:
string value = t.GetValue("Illegal key");
That's why I've come up with this idea:
public class StorageKeys
{
public static StorageKeys SomeKey = new StorageKeys("Foo");
public static StorageKeys AnotherKey = new StorageKeys("Foooo");
private StorageKeys(string key)
{
_key = key;
}
private readonly string _key;
public static implicit operator string(StorageKeys key) => key._key;
}
public interface IStorage
{
string GetValue(StorageKeys key);
}
After these changes my method can be used only with correct keys but I think it would decrease a performance because of static properties and implicit casting.
So my question is it a good idea?
Am I overconcerned?
How much slower my second approach would be comparing to the first one?
Is there another way to prevent passing wrong arguments?
Am I overconcerned?
Short answer, yes.
What you are trying to do is prevent passing an invalid argument which isn't what you are supposed to do in the first place, you should consider using an enum IF that is possible, that makes it 99.9% typesafe and almost no checks would be required.
In a situation where you need that param to be a string, just perform a validation in GetValue(string key) and either return a null if you wish to handle that later or just throw an Exception.
The question is actually very straightforward. The following code throws the exception right below it:
class Foo
{
public const StringBuilder BarBuilder = new StringBuilder();
public Foo(){
}
}
Error:
Foo.BarBuilder' is of type 'System.Text.StringBuilder'. A const field
of a reference type other than string can only be initialized with
null.
MSDN says this, which I understand and it makes sense from const perspective:
A constant expression is an expression that can be fully evaluated at
compile time. Therefore, the only possible values for constants of
reference types are string and a null reference.
However, I don't see the reason why or where we would use null constant. So why in the first place that a reference type (other than string) can be defined with const if it can be only set to null and if it was a deliberate decision (which I believe it is) then where can we use constant with null values?
Update:
When we think of an answer, please let's think differently than "We have this so why not that..." context.
From MSDN
when the compiler encounters a constant identifier in C# source code (for example, months), it substitutes the literal value directly into the intermediate language (IL) code that it produces. Because there is no variable address associated with a constant at run time, const fields cannot be passed by reference and cannot appear as an l-value in an expression.
Because reference types (other than null, and strings which are special) need to be constructed at run time, the above would not be possible for reference types.
For reference types, the closest you can get is static readonly:
class Foo
{
// This is not a good idea to expose a public non-pure field
public static readonly StringBuilder BarBuilder = new StringBuilder();
public Foo(){
}
}
Unlike const substitution (in the calling code), static readonly creates a single shared instance of the reference type which has subtle differences if assembly versions are changed.
Although the reference cannot (normally) be reassigned, it doesn't preclude calling non-pure methods on the StringBuilder (like Append etc). This is unlike consts, where value types and strings are immutable (and arguably should be "eternal").
However, I don't see the reason why or where we would use null constant.
Null constants are useful as sentinel values.
For example, this:
public class MyClass
{
private const Action AlreadyInvoked = null;
private Action _action;
public MyClass(Action action) {
_action = action;
}
public void SomeMethod()
{
_action();
_action = AlreadyInvoked;
}
public void SomeOtherMethod()
{
if(action == AlreadyInvoked)
{
//...
}
}
}
Is much more expressive than this:
public class MyClass
{
//...
public void SomeMethod()
{
_action();
_action = null;
}
public void SomeOtherMethod()
{
if(action == null)
{
//...
}
}
}
The source code for the Lazy<T> class shows Microsoft used a similar strategy. Although they used a static readonly delegate that can never be invoked as a sentinel value, they could have just used a null constant instead:
static readonly Func<T> ALREADY_INVOKED_SENTINEL = delegate
{
Contract.Assert(false, "ALREADY_INVOKED_SENTINEL should never be invoked.");
return default(T);
};
As you state in the question, there is one reference type that can be put into a const reference - strings. The compiler special-cases this and puts the strings into the compiled output and allows them to be read into the reference type at runtime.
Of course this begs the question - why not have strings be the only reference types that can be const, as long as we're special-casing them anyway? To that, I can only speculate that adding a special case in the compiler is simpler and less problematic than adding a special case in the language. From a language perspective, a string is just a reference type, even if the compiler has special handling to create instances of it from string literals and compiled resources.
I think that you are asking that why reference type with null allow as a constant.
I think you are right that it does not make much sense but it is useful if you have designed your own library and if you want to compare with null but want to give special meaning ( like comparing with your library value only rather then directly null)
public class MyClass
{
public const MyClass MyClassNull = null;
public MyClass()
{
}
}
it usage like this.
object obj = GetMyClass();
if(obj == MyClass.MyClassNull) // This going to convert to actual null in MSIL.
{
}
I'm returning values from an Entity object. Some of them are String typed and some are not. Right now, I did a quick solution as follows.
private String GetStringValue(Entity entity, String attribute, String substitute = "")
{
if(entity.Contains(attribute)
return entity[attribute] as String;
return substitute;
}
private String GetIntValue(Entity entity, String attribute, int substitute = 0)
{
if(entity.Contains(attribute)
return entity[attribute] as int;
return substitute;
}
Then I remembered that there's a syntax for generic typing (something like <TypeX>). My question is, however, if there's a point to start changing the existing code. I'll need to change the signature of the method in two places (return type and substitute type) but I fear that I'll need to do some complex coding inside the method as well.
On the other hand, I'd have a nice way to treat all the types possible (and I have a hunch we'll be working with more than strings and integers.
You will have to change the signature of the method in three places, because you also have to add the generic parameter:
private T GetValue<T>(Entity entity, String attribute, T substitute)
Within the method, there's no real need for any complex coding; replacing your current occurrences of string or int, respectively, with T, should suffice. (Note that the as operator can only be applied if you restrict T to reference types - which you probably don't want to do, because int is a value type).
Note that there are two issues with this method that you might consider drawbacks:
This generic method will support "all the types possible", but it will also support any types impossible (users are free to specify whatever type they like for T, and there is no way to restrict T while still supporting both string and int.
You cannot specify arbitrary default substitute values for each type. What you can do is declare a default value for substitute, namely default(T), but at least for string, that is not an empty string, but null.
You are right "something like" is the generic method. Check out generic methods there.
Next method looks good for your purpose.
private static T GetValue<T>(Entity entity, string attribute, T defaultValue)
{
if (!entity.Contains(attribute))
return defaultValue;
return (T)entity[attribute];
}
EDIT: updated according of the w0lf's comment.
If you don't want to change method signature, you can write a generic function and call it from all of these non generic versions.
private String GetStringValue(...){
return GetValue<String>(...);
}
By the way, you are looking for Generic methods
For e.g (from msdn)
static void Swap<T>(ref T lhs, ref T rhs)
{
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
...
Swap<int>(ref a, ref b);
or just
Swap(ref a, ref b); //type int is infered based on type of arguements and method signature
What class is Entity? Assuming it's a custom class, make it also generic, then this works:
private T Get<T>(Entity<T> entity, T attribute, T substitute = default(T))
{
if (entity.Contains(attribute))
return entity[attribute];
return substitute;
}
You can retrieve the value in this way:
var entity = new Entity<string>();
string val = Get<string>(entity, "attr", "subst");
You should define your Entity<T> class:
public class Entity<T>
{
// TODO: implement
public T this[string i] { get; set; }
// TODO: implement
internal bool Contains(string attribute)
{
return true;
}
// TODO: implement
// other properties and methods
}
And you may use a generic method:
private T GetStringValue<T>(Entity<T> entity, String attribute, T substitute = default(T))
{
if (entity.Contains(attribute))
return entity[attribute];
return substitute;
}
If it is possible to generalize the code inside a method I would absolutely recommend to use it in a generic way. It makes the class smaller, better readable and you just have to change one method if requirements change. Your method looks like it can be made generic easily.
private T GetIntValue<T>(Entity entity, String attribute, T substitute = default(T))
{
if(entity.Contains(attribute))
return (T)entity[attribute];
return substitute;
}
If there would be some more logic to execute you could also use a dictionary with functions for the different types:
private IDictionary<Type, Func<Entity, string, object>> actions;
private void InitActions()
{
actions = new Dictionary<Type, Func<Entity, string, object>>
{
{
typeof (string), (entity, attribute) =>
{
// this could be your custom code for string
return entity[attribute];
}
},
{
typeof (int), (entity, attribute) =>
{
// this could be your custom code for int
return entity[attribute];
}
}
};
}
private T GetIntValue<T>(Entity entity, String attribute, T substitute = default(T))
{
if (entity.Contains(attribute) && actions.ContainsKey(typeof (T)))
{
Func<Entity, string, object> action = actions[typeof (T)];
return (T)action(entity, attribute);
}
return substitute;
}
I have a project I am working that will involve creating one DLL that will be used across multiple other sites. Inside this DLL we need to reference about 10 Enums. The values of these Enums however will be different for each site the DLL is used on. For example:
MyBase.dll may have a class MyClass with an attribute of type MyEnum.
MyBase.dll is then referenced in MySite. MyStie will also reference MyEnums.dll which will contain the values for the MyEnum type.
Is there any way to accomplish this? While building MyBase.dll, I know what enums will exist in side of MyEnums.dll. The problem is I cannot build MyBase.dll without specifically referenceing the MyEnums.dll, which is not created until the MyBase.dll is used in a specific project.
I hope that makes sense and hope I can find an answer here.
Thanks.
Edit:
Thanks for all the comments. It will take a few reads to completely understand, but let me try to give a better example of what I am looking at here.
Lets say the following code is in my DLL that will be put into various projects. Status is an enum.
public Class MyClass
{
private Status _currentStatus;
public Status CurrentStatus
{
get
{
return _currentStatus;
}
}
public void ChangeStatus(Status newStatus)
{
_currentStatus = newStatus;
}
}
What I want to be able to do is the define the possible values for Status in the individual projects. So in this DLL, I will never reference what values might be in the Status enum, I just have to know that it exists.
I hope that is a bit more clear on what I am trying to do.
If you want each client to see different enum values (in a different assembly version), then using an enum is a bad solution - changes will break client code...
Using an enum might work (as long as the enum names and assembly name are the same and the assembly isn't signed) - you could just swap the assembly. However, if a value is used anywhere in the code that isn't there at the end you'll end up with an exception. Also, you may have the explicitly number the values, to make sure different subsets of the values won't end up with the same number for different values or different numbers for the same value.
Instead consider using a dynamically built collection, e.g. a list, a dictionary or a database table. Or just give the same assembly with the same superset of enum values to everyone and let the users decide which values are relevant to them (perhaps use significant prefixes for values as a convention).
Or you could use a combination of the two...
Generate a different structure (different type name (or namespace) and assembly name) per site with different properties (according to site's profile) and one master structure for the service that accepts the structures. Have all the structures implement the same interface, which you expect to receive...
public interface IStatus
{
string GetKey();
}
public struct ClientXStatus : IStatus
{
private readonly string _key;
private ClientXStatus(string key)
{
_key = key;
}
// Don't forget default for structs is 0,
// therefore all structs should have a "0" property.
public ClientXStatus Default
{
get
{
return new ClientXStatus();
}
}
public ClientXStatus OptionB
{
get
{
return new ClientXStatus(10);
}
}
string IStatus.GetKey()
{
return _key;
}
public override bool Equals(object obj)
{
return (obj is IStatus) && ((IStatus)obj).GetKey() == _key;
}
public override int GetHashCode()
{
return _key.GetHashCode();
}
public static bool operator==(ClientXStatus x, IStatus y)
{
return x.Equals(y);
}
public static bool operator==(IStatus x, ClientXStatus y)
{
return y.Equals(x);
}
public static bool operator!=(ClientXStatus x, IStatus y)
{
return !x.Equals(y);
}
public static bool operator!=(IStatus x, ClientXStatus y)
{
return !y.Equals(x);
}
// Override Equals(), GetHashCode() and operators ==, !=
// So clients can compare structures to each other (to interface)
}
Use a master struct for the service:
public struct MasterStatus : IStatus
{
private readonly string _key;
private MasterStatus(string key)
{
_key = key;
}
// Don't forget default for structs is 0,
// therefore all structs should have a "0" property.
public MasterStatus Default
{
get
{
return new MasterStatus();
}
}
// You should have all the options here
public MasterStatus OptionB
{
get
{
return new MasterStatus(10);
}
}
// Here use implicit interface implementation instead of explicit implementation
public string GetKey()
{
return _key;
}
public static implicit operator MasterStatus(IStatus value)
{
return new MasterStatus(value.GetKey());
}
public static implicit operator string(MasterStatus value)
{
return new value._key;
}
// Don't forget to implement Equals, GetHashCode,
// == and != like in the client structures
}
Demo service code:
public void ServiceMethod(IStatus status)
{
switch (status.GetKey())
{
case (string)MasterStructA.OptionB:
DoSomething();
}
}
Or:
public void ChangeStatus(IStatus status)
{
_status = (MasterStatus)status;
}
This way you:
Use code generation to prevent collision of values.
Force users to use compile time checks (no int values or string values) by hiding values (as private) and only accepting your structures.
Use real polymorphism in the service's code (an interface) and not a error-prone hack.
Use immutable value types (like enums) and not reference types.
First you have to decide WHERE to put your constants. Then you can transform your enum to static properties.
For example:
public enum MyEnum
{
Value1,
Value2
}
Can be changed to (first naive approach):
public static class MyFakeEnum
{
public static int Value1
{
get { return GetActualValue("Value1"); }
}
public static int Value2
{
get { return GetActualValue("Value2"); }
}
private static int GetActualValue(string name)
{
// Put here the code to read the actual value
// from your favorite source. It can be a database, a configuration
// file, the registry or whatever else. Consider to cache the result.
}
}
This simply will provide required constants but you'll have to throw away compile-time check for the type if you'll need MyFakeEnum as parameter. For a better solution you can follow, for example, what Microsoft did (more or less) for System.Drawing.Color.
public sealed class MyFakeEnum
{
public static readonly MyFakeEnum Value1 = new MyFakeEnum("Value1");
public static readonly MyFakeEnum Value2 = new MyFakeEnum("Value2");
private MyFakeEnum(string name)
{
_name = name;
}
public static implicit operator int(MyFakeEnum value)
{
return GetActualValue(value._name);
}
private string _name;
}
Of course you should provide proper overides at least for Equals, GetHashCode and ToString.
Pro
It can be an upgrade from an existing enum. Code won't be breaked and you may just need to recompile.
You can use it as strongly typed parameter. For example: void DoSomething(MyFakeEnum value) is valid and callers can't pass something else (note that this is one of the reasons because enums are considered weak).
If you implement all the required operators you can use the normal syntax for comparison: value == MyFakeEnum::Value1.
With a little bit of code you may even implement the FlagsAttribute syntax.
You do not change the normal syntax of enums: MyFakeEnum.Value1.
You can implement any number of implicit/explicit conversion operators to/from your type and any conversion will be safe and checked in the point it's done (this is not true again with standard enums).
You do not have hard-coded strings that can be breaked by changes and won't be catched until they cause a run-time error (yes, run-time). Using, for example, a dictionary if you'll change the definitions then you'll have to search all your code for that string.
Cons
First implementation is longer because you have to write support code (but for any new value you'll simply add a new line).
Value list is fixed and must be known at compile time (this is not an issue if you're searching a replacement for an enum because it's fixed too).
With this solution you may save more or less the same syntax you had with standard enums.
is it possible to define an extension method that at the same time is an operator?
I want for a fixed class add the possibility to use a known operator that actually can't be applied.
For this particular case i want to do this:
somestring++; //i really know that this string contains a numeric value
And i don't want to spread types conversions for all the code.
I know that i could create wrapper class over an string and define that operator but i want to know if this kind of thing is possible to avoid search-and-replace every string declaration with MySpecialString.
Edited: as most have say string is sealed, so derivation isn't possible, so i modify "derived" to "wrapper", my mistake.
That is not possible in C#, but why not a standard extension method?
public static class StringExtensions {
public static string Increment(this string s) {
....
}
}
I think somestring.Increment() is even more readable, as you're not confusing people who really dont expect to see ++ applied to a string.
A clear example of where this would be useful is to be able to extend the TimeSpan class to include * and / operators.
This is what would ideally work...
public static class TimeSpanHelper
{
public static TimeSpan operator *(TimeSpan span, double factor)
{
return TimeSpan.FromMilliseconds(span.TotalMilliseconds * factor);
}
public static TimeSpan operator *(double factor, TimeSpan span) // * is commutative
{
return TimeSpan.FromMilliseconds(span.TotalMilliseconds * factor);
}
public static TimeSpan operator /(TimeSpan span, double sections)
{
return TimeSpan.FromMilliseconds(span.TotalMilliseconds / factor);
}
public static double operator /(TimeSpan span, TimeSpan period)
{
return span.TotalMilliseconds / period.TotalMilliseconds);
}
}
No, it is not possible to do from outside of the class. ++ operator should be defined inside class which is being incremented. You can either create your own class which will be convertible from string and will have ++ overload or you can forget about this idea and use regular methods.
No, you can't have an extension method which is also an operator. Extension methods can only be declared in static classes, which can't have instances and according to the C# spec,
User-defined operator declarations always require at least one of the parameters to be of the class or struct type that contains the operator declaration. [7.3.2]
Therefore, it is impossible for an extension method to also be an overloaded operator.
Additionally, you can't override System.String since it is a sealed class.
The string class is sealed in C#, so creating a string-derived class actually isn't possible.
That being said, an extension method will of course work just fine (as will a standard static method in a helper class) but it won't be an operator, just ordinarily-named method.
Currently this is not supported because Extension methods are defined in separate static class and static classes cannot have operator overloading definitions.
This is all true, but it would be nice for M$ to add this functionality in the future. Sometimes the framework is just missing things and an extension can help plug the gap (or fix the issue) this can sometimes be operators.
An example. To compare IP Addresses, you must use the Equals method to directly compare (of course parts of the struct could also be compared as could the address bytes individually - but that's another story). However, using the == operator always returns false at the object level (i.e. without converting them to strings etc). How hard is it to put the Equals method call inside the == operator call (that's rhetorical), but we can't do it. This is inconsistant and a place for bugs to creep in (note it does not fail, just always equates to false - whereas Equals does not).
I would argue that you should use a wrapper class, even if you could write an extension operator.
//i really know that this string contains a numeric value
is exactly the sort of situation that type-safety was invented for.
Another way of looking at it is that by writing that operator, you have broken many other functions and operators that work with the string class, since they don't necessarily preserve the property of containing a numeric value. By using a wrapper class, not a derived class, you only re-implement those features of string that make sense for numeric strings.
i was in a very similar situation as you described: i needed to increase the text (containing a numeric value for sure) in a Windows Forms textbox.
I understand your need as you described
somestring++; //i really know that this string contains a numeric value
My soultion is something like that which i believe is close to your description
somestring = (incrementable)somestring + 1
All i needed to do was
creating class called incrementable
defining an explicit operator in it (to aid converting string to incrementable )
defining an implicit operator in it (to aid converting incrementable back to string )
operator for + (plus sign)
Here's how my class looks in complete
public class incrementable
{
public string s; // For storing string value that holds the number
public incrementable(string _s)
{
s = _s;
}
public static explicit operator incrementable(string tmp)
{
return new incrementable(tmp);
}
public static implicit operator string(incrementable tmp)
{
return tmp.s;
}
public static incrementable operator +(incrementable str, int inc) // This will work flawlessly like `somestring = (incrementable)somestring + 1`
=> new incrementable((Convert.ToInt32(str.s) + inc).ToString());
public static incrementable operator ++(incrementable str) // Unfortunately won't work, see below
=> new incrementable((Convert.ToInt32(str.s) + 1).ToString());
}
Unfortunately i just couldn't get managed to improve my class by the usage of unary ++ operator. The reason against of usage of implicit conversion like ((incrementable)somestring)++ is that it is going to result in error saying The operand of an increment or decrement operator must be a variable, property or indexer hence can not be result of that casting.
Anyway, hope this helps!
As shown in the other answers, it cannot be done directly. But what if you need it, say you want to improve StringBuilder like
void Main()
{
var log = (StringBuilder)"Hello ";
log += "World!";
log += "\nThis example shows how to extend StringBuilder";
log.ToString().Dump();
}
how can you achieve this (i.e. use + operator instead of sb.Append(str);) ?
Answer:
In this case, you can't do it directly, but what you can do is:
Run it in DotNetFiddle
void Main()
{
var log = (StrBuilder)"Hello "; // same as: "Hello ".ToStrBuilder();
log += "World!";
log += "\nThis example shows how to extend StringBuilder";
log.ToString().Dump();
}
public static class Extensions
{
public static StrBuilder ToStrBuilder(this string str)
{
return new StrBuilder(str);
}
}
public class StrBuilder
{
private StringBuilder sb;
public StrBuilder()
{
sb = new StringBuilder();
}
public StrBuilder(string strB)
{
sb = new StringBuilder(strB);
}
public static implicit operator StrBuilder(string self)
{
return new StrBuilder(self);
}
public static StrBuilder operator +(StrBuilder sbA, string strB)
{
return sbA.Append(strB);
}
public StrBuilder Append(string strB)
{
sb.Append(strB);
return this;
}
public override string ToString()
{
return sb.ToString();
}
}
Note: You can't inherit from StringBuilder because it is a sealed class, but you can write a class that "boxes" a StringBuilder - which is, what is done here (thanks to IanNorton's answer regarding implicit conversion).