This question already has an answer here:
Why do I have to copy "this" when using LINQ in a struct (and is it OK if I do)?
(1 answer)
Closed 7 years ago.
Apparently you cannot use the keyword "this" in a method in a struct.
Note that in the below example I do not explicitly type "this" but it is implied when I reference the properties "X" or "Y".
My struct:
public struct Coord
{
public int X;
public int Y;
public Coord(int x, int y)
{
X = x;
Y = y;
}
// some other methods omitted
public List<int> GetPossibles()
{
return LaurenceAI.Values.Where(n => LaurenceAI.Possibilities[X, Y, n]).ToList();
}
}
usage example:
foreach(int numeral in targetCoord.GetPossibles())
{
//do stuff
}
Error:
Error 1 Anonymous methods, lambda expressions, and query expressions inside structs cannot access instance members of 'this'. Consider copying 'this' to a local variable outside the anonymous method, lambda expression or query expression and using the local instead. C:\Projects\Sodoku\SodokuSolver\Sodoku\LaurenceAI.cs 367 74 Sodoku
Questions:
What is the technical reason that a method in a struct cannot use keyword "this"?
Is there an elegant way to fix this so that I don't have to type out the reflection code longhand every time I want a list of possible numerals for a given Coord?
The reason is that structs are passed by value, not by reference. Using this in this context results in typically not what you want - it'll access the this pointer of the copy, not the outer object, and it'll be really confusing when any assignments you make aren't showing in the outer call. It's annoying in this specific circumstance, but in general it's stopping more weird errors.
The error message actually gives you a fairly reasonable solution - copy the values first. Do something like:
public List<int> GetPossibles()
{
var localX = X;
var localY = Y;
return LaurenceAI.Values.Where(n => LaurenceAI.Possibilities[localX, localY, n]).ToList();
}
Related
This question already has answers here:
Why can I not modify the result of an unboxing conversion?
(3 answers)
Closed 7 years ago.
Let's look at the following code.
struct SPoint
{
public int x;
public int y;
public SPoint(int x, int y)
{
this.x = x;
this.y = y;
}
}
class Test
{
public static void Main()
{
SPoint s = new SPoint(3, 4);
object o = s;
((SPoint) o).x = 5;
}
}
Why isn't the last assignment possible? What is the reason for such behaviour?
Since s is a struct (a.k.a: a value type), (SPoint)o is a copy of the data:
From the C# language spec (§1.3, "Types and Variables"):
When a value of a value type is converted to type object, an object instance, also called a “box,” is allocated to hold the value, and the value is copied into that box. Conversely, when an object reference is cast to a value type, a check is made that the referenced object is a box of the correct value type, and, if the check succeeds, the value in the box is copied out.
The language protects you from changing the data of the cloned value type without putting it in a variable first, since you might think that you are changing the original s.x value while you are changing it's temporary (not - variabled) clone, unlike unsafe languages like C++/CLI where this kind of assignments might be allowed.
If you want, you are able to explicitly create a new variable and do your manipulations in it:
SPoint cloneOfS = ((SPoint)o);
cloneOfS.x = 5;
See MSDN:
The result of an unboxing conversion is a temporary variable. The compiler prevents you from modifying such variables because any modification would go away when the temporary variable goes away. To fix this, declare a new value-type variable to store the intermediate expression, and assign the result of the unboxing conversion to that variable.
I started my journey with C# but I realised that I have some problems with some basic information about memory when it comes to declaration of variables. See if I am correct.
int x; // I declared variable of type int, which name is x. Compiler will provide memory for it but we dont have known value of it.
x=10; // Now memory location is still the same but value now kept there is 10;
public struct Point {
public int x, y;
}
Now I define a struct named Point. Beacuse struct is a value type, it again has reserved memory for it on the computer. Howewer x and y have no value.
Now Point p1 = new Point(); // what is happening here? Struct is not a reference type. So is this just initialization of Point variable with the default constructor without assigning values to x and y?
Second short question. When I write a code like:
int x = 10;
Can I say that I created instance of class integer which value is 10 and name x;
I would be grateful for help.
// what is happening here? Struct is not a reference type. So is this just initialization of Point variable with the default constructor without assigning values to x and y?
No; there are 4 possible scenarios here:
a class: the memory space is wiped to all 0s, then any custom constructor is invoked, which may also involve field initializers
a struct called without a custom constructor: the memory space is wiped to all 0s
a struct called with a custom constructor: the custom constructor is required to assign all the fields
a struct variable used without ever calling a constructor: this is actually a thing, but the calling code must write to all the fields before they can do anything else with it; since most structs do not expose their fields, this rarely works
Second short question. When i write a code like:
int x = 10;
Can i say that i created instance of class integer which value is 10 and name x; I would be grateful for help.
Not really, because in C# terms, int is not a class (it might be in IL terms). Simply: you have declared a local variable of type int with name x and assigned it the value 10, if this is in a method. If this is a class field, then: you have declared a private instance field of type int named x with a field-initializer giving it the value of 10.
Incidentally, you should avoid public fields in general, and mutable fields on structs. You might prefer:
public struct Point {
private readonly int x, y;
public int X { get { return x; } }
public int Y { get { return y; } }
public Point(int x, int y) { this.x = x; this.y = y'; }
}
This will avoid a huge range of problems.
In C# the default struct constructor sets the struct memory to 0, effectively setting all variables to their default values.
In case of ints, it will be 0. For reference types, it will result in null.
(in other words, for any type T it will be default(T)).
Note that when you write a custom constructor in a struct, you must initialize all member fields.
When you write
int x;
this is similar to
Point p1 = new Point(); (considering Point structure is already defined)
in both the cases all integer variables will have default value of 0 and not null, which is is basically what is used in C# to denote 'nothing' and can be assigned only to reference types.
As well, in c# everything is a class, so when you write
int x = 10;
you are creating an instance of class Int32, though the run time will handle this as value type instead of ref type, as special case.
Same is true for other basic types like, Long, DateTime and few others
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Detailed Explanation of Variable Capture in Closures
public class Polynom {
public delegate double Func(double x);
private Func f;
public Polynom(params double[] coef) {
f = (double x) => {
double sum = 0;
for ( int i = 0 ; i < coef.Length ; i++ )
sum += coef[i] * Math.Pow(x,coef.Length-1-i);
return sum;
};
}
public double evaluate(double x) {
return f(x);
}
public static void Main() {
Polynom a=new Polynom(1,1,1);
Polynom b=new Polynom(2 , 2 , 0);
Console.WriteLine(a.evaluate(2));
Console.WriteLine(b.evaluate(2));
Console.ReadKey();
}
}
Notice how the code in f uses coef, while coef is a paramater of the constructor.
if you think about it, that should not work unless it gets a ref copy of coef, because once the constructor done its job, its parameters are suppose to vanish. but somehow, calling f manages to use coef as if it still exists. HOW?
I would love a good deep explantion if someone can explain this...
Another thing that i would like to know is, the code is the same on every Polynom instance, but does every instance get another copy of that same code? if so, is there a way to make my class run with just 1 copy of that code? (like make it static somehow)
Lambdas and other delegates are implemented as closures, special objects created by the compiler that combine a method of your lambda with all the data that the lambda needs to complete its execution. The values of all local variables and parameters that are used inside the lambda are implicitly captured as data members of the closure, so they remain available until the lambda itself is no longer referenced.
You can think of the closure as a special anonymous class created specifically for your lambda. In your case, a closure may look like this:
private Polynom_Closure {
private readonly double[] coef;
public Polynom_Closure(double[] coef) {
this.coef = coef;
}
public double evaluate(double x) {
double sum = 0;
for ( int i = 0 ; i < coef.Length ; i++ )
sum += coef[i] * Math.Pow(x,coef.Length-1-i);
return sum;
}
}
The compiler makes this class invisibly for you, and then inserts its use into your code:
public Polynom(params double[] coef) {
f = new Polynom_Closure(coef).evaluate;
}
The function is a so-called closure, which is well-explained in this wikipedia article
A closure allows a function to access variables outside its immediate lexical scope. An upvalue is a free variable that has been bound (closed over) with a closure. The closure is said to "close over" its upvalues. The referencing environment binds the nonlocal names to the corresponding variables in scope at the time the closure is created, additionally extending their lifetime to at least as long as the lifetime of the closure itself. When the closure is entered at a later time, possibly from a different scope, the function is executed with its non-local variables referring to the ones captured by the closure.
Concerning your second question: Making a closure static would somewhat contradict the purpose of functional principles.
can anyone suggest me the exact use of out keyword as a paramter, and how its connected for returning multiple values from the function, as in this POST, i am confused with out variable with normal variable. can anyone help me for this.
This is frequently confusing, and I think the MSDN documentation actually is a bit "clear only if already known". That is, it is correct, but it really only makes sense if you already understand the concept.
Here's how I think of it.
A regular parameter makes a copy of the value of the argument. When you say:
static int M(int z) { z = z + 1; return z; }
...
int x = 123;
int y = M(x);
That is just like you said:
int x = 123;
int z = x; // make a copy of x
z = z + 1;
int y = z;
A ref or out parameter make an alias for an existing variable. When you say
static void N(ref int q) { q = q + 1; }
...
int x = 123;
N(x);
That is the same as saying:
int x = 123;
// MAGIC: q is now an another name for variable x
q = q + 1;
q and x are two different names that refer to the same variable. Incrementing q also increments x because they are the same. z and x in the previous example are two different names that refer to two different variables. Incrementing z does not change x.
Summing up: "out" and "ref" just mean "do not make a new variable; rather, temporarily make a second name for an existing variable".
Is that now clear?
UPDATE: I did not say what the difference between "out" and "ref" is. The difference is simple. On the "caller" side, a "ref" must be a definitely assigned variable before the method is called. An "out" need not be. On the "callee" side, a "ref" may be read before it is written to, but an "out" must be written to before it is read. Also, an "out" must be written to before control leaves the method normally.
MSDN documentation already does a great job explaining this:
The out keyword causes arguments to be passed by reference. This is
similar to the ref keyword, except that ref requires that the variable
be initialized before being passed. To use an out parameter, both the
method definition and the calling method must explicitly use the out
keyword. For example:
class OutExample
{
static void Method(out int i)
{
i = 44;
}
static void Main()
{
int value;
Method(out value);
// value is now 44
}
}
It's very frequently used in a pattern that "tries" to get a value, something like:
int result;
if(Int32.TryParse("123", out result))
{
Console.WriteLine(result + 1);
}
out keyword should be used when you want to:
a) Allow your function to modify specific variable from calling code stack AND
b) enforce setting this variable value inside your function
MSDN is always a good place to start
In most languages c# included you can pass values in 2 ways, by value, by reference.
by value gives the method a copy of your data, so changing the data wont have any effect on the original data
by reference essentially gives the method the memory address of your data, so if the method modifies the data, it changes the original.
Out is a special type of ref, in that you do not need to initialise the variable before you call the method, it can be called with null being passed in. and it MUST be set by the method.
Another way you can think of it (from the outside code's point of view) is:
val = read only
ref = read/write
out = write only.
http://msdn.microsoft.com/en-us/library/t3c3bfhx(v=vs.80).aspx
out keyword is good if you want to return multiple values of pre-defined types (for example an int, a List<string> and a DateTime), and you don't want to create a new class just for this purpose.
Ok,
let look at the usual pattern for this kind of function - the TrySomething.
Suppose you have a function that might succeed giving you an value or not but you don't won't to use an exception for this because you don't want the overhead or it's a common trait.
Then you normaly return true if the method suceeded and false if not. But where would you put your outputvalue to?
One possible answer is using an out parameter like this:
bool TrySomething(MyInputType input, out MyOutputType output)
{
output = default(MyOutputType);
/* ... Try getting the answer ... */
if (!successful)
return false;
output = successfulOutput;
return true;
}
Remark:
Or you might consider using a Tuple<bool,MyOutputType> and indeed F# interpretes the pattern above as resulting in such a tuple by itself.
This feels like a too easy question to be found with google, I think/hope I've got stuck in the details when trying to implement my own version of it. What I'm trying to do is to sort a list of MyClass objects depending on my Datatype object different search functions should be used.
I've had something like this in mind for the class Datatype:
class Datatype {
public delegate int CMPFN(object x, object y);
private CMPFN compareFunction;
(...)
private XsdDatatype((...), CMPFN compareFunction) {
(...)
this.compareFunction = compareFunction;
}
public CMPFN GetCompareFunction() {
return this.compareFunction;
}
static private int SortStrings(object a, object b) {
return ((MyClass)a).GetValue().CompareTo(((MyClass)b).GetValue());
}
}
And later on I'm trying to sort a MyClass list something like this:
List<MyClass> elements = GetElements();
Datatype datatype = new Datatype((...), Datatype.SortStrings);
elements.Sort(datatype.GetCompareFunction()); // <-- Compile error!
I'm not overly excited about the cast in Datatype.SortStrings but it feels like this could work(?). The compiler however disagrees and gets me this error on the last line above and I'm a bit unsure exactly why CMPFN can't be converted/casted(?) to IComparer.
Cannot convert type 'proj.Datatype.CMPFN' to 'System.Collections.Generic.IComparer<proj.MyClass>'
Delegates aren't duck-typed like that. You can create an Comparison<MyClass> from a CMPFN but you can't use a plain reference conversion - either implicit or explicit.
Three options:
Create the comparer like this:
elements.Sort(new Comparison<MyClass>(datatype.GetCompareFunction()));
Use a lambda expression to create a Comparison<T> and use that instead:
elements.Sort((x, y) => datatype.GetCompareFunction()(x, y));
Write an implementation of IComparer<MyClass> which performs the comparison based on a CMPFN
Note that the second approach will call GetCompareFunction once per comparison.
A much better solution would be to get rid of CMPFN entirely - why not just use (or implement) IComparer<MyClass> to start with? Note that that would remove the casts as well. (If you're happy using delegates instead of interfaces, you could express the comparison as a Comparison<MyClass> instead.)
Note that as of .NET 4.5, you can use Comparer.Create to create a Comparer<T> from a Comparison<T> delegate.
I'm not sure why your current API is in terms of object, but you should be aware that in C# 3 and earlier (or C# 4 targeting .NET 3.5 and earlier) you wouldn't be able to convert an IComparer<object> into an IComparer<MyClass> (via a reference conversion, anyway). As of C# 4 you can, due to generic contravariance.
There are a number of overloads of List<T>.Sort, but there are none which take a delegate with the parameters you have defined (two objects).
However, there is an overload that takes a Comparison<T> delegate, which you can work with your code with a few minor modifications. Basically, you just replace your CMPFN delegate with Comparison<MyClass> - as an added bonus, you get strong-typing in your SortStrings function, too:
static private int SortStrings(MyClass a, MyClass b) {
return a.GetValue().CompareTo(b.GetValue());
}
public Comparison<MyClass> GetCompareFunction() {
return SortStrings; // or whatever
}
...
elements.Sort(datatype.GetCompareFunction());
Try something like this
class AttributeSort : IComparer<AttributeClass >
{
#region IComparer Members
public int Compare(AttributeClass x, AttributeClass y)
{
if (x == null || y == null)
throw new ArgumentException("At least one argument is null");
if (x.attributeNo == y.attributeNo) return 0;
if (x.attributeNo < y.attributeNo) return -1;
return 1;
}
#endregion
}
You can call it then like this
List<AttributeClass> listWithObj ....
listWithObj.Sort(new AttributeSort());
Should work like you want. You can create a type-safe comparer class as well.