How to Create a New Operator in C#

Is it possible to create a new operator in c#?

No, it is not possible. You would need to create a method instead

Define new operators in C#?

This is not built into the language. You are stuck with overloading the predefined operators that come with the language (overloadable operators).

If you like that style of debugging you might want to consider F#. It is a functional language that runs on top the .NET framework and gives you the ability to define any operator you want.

How new operator works with delegates in C#

how does new MyDel(this.WelcomeUser) work?

It is a call to a constructor, with this.WelcomeUser as an argument.

public delegate string MyDel(string str);

Is a Type definition. The compiler uses this to generate a class deriving from System.Delegate. Note that this was designed before C# had generics.

what is exactly this.WelcomeUser?

It is the name of a method. In C# (and C, C++ etc) a method is always followed by a parameter (or argument) list, even if that list is empty: SomeMethod().

Omitting the list is the equivalent of adress-of.

It becomes clearer when you look at VB.NET, the equivalent code is

MyEvent += new MyDel(this.WelcomeUser);       // C#

AddHandler MyEvent, AddressOf Me.WelcomeUser ' VB

And from C# 2 on, you can use the short notation:

MyEvent += this.WelcomeUser;       // modern C#

What is new without type in C#?

In the specific case of throw, throw new() is a shorthand for throw new Exception(). The feature was introduced in c# 9 and you can find the documentation as Target-typed new expressions.

As you can see, there are quite a few places where it can be used (whenever the type to be created can be inferred) to make code shorter.

The place where I like it the most is for fields/properties:

private readonly Dictionary<SomeVeryLongName, List<AnotherTooLongName>> _data = new();

As an added note, throwing Exception is discouraged as it's not specific enough for most cases, so I'd not really recommend doing throw new ("error");. There are quite a lot of specific exceptions to use, and if none of those would work, consider creating a custom exception.

Should I use new operator in C# Structures while declaring member functions in it?

Although you don't need the new to instantiate a structure, the compiler will not let you use any method or property unless all of its fields are initialized.

You can either create a constructor instead of the setvalue method, or assign it one after the other:

StructureMethods book1;
book1.author = "ds";
book1.name = "";
book1.page = 1;
book1.id = 3;
book1.printinfo();

StructureMethods book2 = new StructureMethods("test","bbb",0,1);
book2.printinfo();

struct StructureMethods
{
public string name;
public string author;
public int page;
public int id;

public StructureMethods(string a, string b, int c, int d)
{
name = a;
author = b;
page = c;
id = d;
}

public void printinfo()
{
Console.WriteLine("Name : " + name);
Console.WriteLine("Author : " + author);
Console.WriteLine("Total Page No : " + page);
Console.WriteLine("ID : " + id);
}
}

Side-Note1: there is no need to use return; at the end of the function unless you are returning some value in a non-void method.

Side-Note2: Since you mentioned you are new to C#, be sure you understand when to use structs and when classes. You can start here

How to use new operator with a template in C#

#1: New constraint with interface

Add a contraint to TValue telling the compiler it has a parameterless constructor. You can do this by adding the keyword new to the contraint of TValue. This way you can at least construct an item.

You cannot use paramters of generic parameter types. But you can use another contraint to define some properties:

public interface IMyValue<TValue>
{
void CopyFrom(TValue original);
}

public static List<TValue> deepCopyList<TValue>(List<TValue> src)
where TValue: IMyValue<TValue>, new() // <== Setting the constraints of TValue.
{
List<TValue> arr = new List<TValue>();

for (int i = 0; i < src.Count; i++)
{
TValue value = new TValue();
value.CopyFrom(src[i]);
arr.Add(value); // No error.
}

return arr;
}

#2: Using ICloneable

There is a second solution, and it is a bit the same. Make the value responsible for cloning it self, using ICloneable:

public static List<TValue> deepCopyList<TValue>(List<TValue> src)
where TValue: ICloneable // <== Setting the constraints of TValue.
{
List<TValue> arr = new List<TValue>();

for (int i = 0; i < src.Count; i++)
{
TValue value = (TValue)src[i].Clone();
arr.Add(value); // No error.
}

return arr;
}

#3: Using Activator

But since you want to create a deep clone, there is another way, using the Activator. This method is NOT type safe and can produce runtime exceptions when the type does not support that constructor call:

public static List<TValue> deepCopyList<TValue>(List<TValue> src)
{
List<TValue> arr = new List<TValue>();

for (int i = 0; i < src.Count; i++)
{
TValue value = (TValue)Activator.CreateInstance(typeof(TValue), src[i]);
arr.Add(value); // Possible runtime rror.
}

return arr;
}

Above method can also be replace by using reflection and get the correct ConstructorInfo and use this to create new items. It is the same thing what Activator does and has the same risk.

BTW: In C# it is called 'generic', not 'template' as in C++.

Dilemma with using value types with `new` operator in C#

First let me correct your errors.

When operator new() is used with reference type, space for the instance is allocated on the heap and reference variable itself is placed on the stack.

The reference that is the result of "new" is a value, not a variable. The value refers to a storage location.

The reference is of course returned in a CPU register. Whether the contents of that CPU register are ever copied to the call stack is a matter for the jitter's optimizer to decide. It need not ever live on the stack; it could live forever in registers, or it could be copied directly from the register to the managed heap, or, in unsafe code, it could be copied directly to unmanaged memory.

The stack is an implementation detail. You don't know when the stack is being used unless you look at the jitted code.

p variable is on the stack and the created instance of Person (all of its memebers) is on the heap. p.id would be 0 and p.name would be null.

Correct, though of course again p could be realized as a register if the jitter so decides. It need not use the stack if there are available registers.

You seem pretty hung up on this idea that the stack is being used. The jitter might have a large number of registers at its disposal, and those registers can be pretty big.

I'm coming from C++ background.

Ah, that explains why you're so hung up on this stack vs heap thing. Learn to stop worrying about it. We've designed a managed memory environment where things live as long as they need to. Whether the manager chooses to use stack, heap or registers to efficiently manage the memory is up to it.

In first line someDate variable is allocated on the stack. Precisely 12 bytes.

Let's suppose for the sake of argument that this 12 byte structure is allocated on the stack. Seems reasonable.

My question is what happens on the second line? What does operator new() do? Does it only zero-out members of Date structure or it allocates space on the heap as well?

The question presupposes a false dichotomy and is therefore impossible to answer as stated. The question presents two either-or alternatives, neither of which is necessarily correct.

On one side I wouldn't expect new to allocate space on the heap, of course because in the first line memory is already allocated on the stack for the structure instance.

Correct conclusion, specious reasoning. No heap allocation is performed because the compiler knows that no part of this operation requires a long-lived storage. That's what the heap is for; when the compiler determines that a given variable might live longer than the current method activation, it generates code which allocates the storage for that variable on the long-lived "heap" storage. If it determines that the variable definitely has a short lifetime then it uses the stack (or registers), as an optimization.

On the other hand, I would expect new to allocate space on the heap and return address of that space, because that's what new should do.

Incorrect. "new" does not guarantee that heap is allocated. Rather, "new" guarantees that a constructor is called on zeroed-out memory.

Let's go back to your question:

Does it only zero-out members of Date structure or it allocates space on the heap as well?

We know it does not allocate space on the heap. Does it zero out members of the date structure?

That's a complicated question. The specification says that what happens when you say

someDate = new Date();    
  • the address of someDate is determined
  • space is allocated (off "the stack") for the new object. It is zeroed out.
  • then the constructor, if any, is called, with "this" being a reference to the new stack storage
  • then the bytes of the new stack storage are copied to the address of someDate.

Now, is that actually what happens? You would be perfectly within your rights to notice that it is impossible to tell whether new stack space is allocated, initialized and copied, or whether the "old" stack space is initialized.

The answer is that in cases where the compiler deduces that it is impossible for the user to notice that the existing stack space is being mutated, the existing stack space is mutated and the extra allocation and subsequent copy are elided.

In cases where the compiler is unable to deduce that, then a temporary stack slot is created, initialized to zeros, constructed, mutated by the constructor, and then the resulting value is copied to the variable. This ensures that if the constructor throws an exception, you cannot observe an inconsistent state in the variable.

For more details about this issue and its analysis by the compiler see my article on the subject.

https://ericlippert.com/2010/10/11/debunking-another-myth-about-value-types/

C# new operator - different between assignment to variable and without

You don't. Creating that object has no side effects, and the reference is never stored. So not only may it be garbage collected immediately after creation, the runtime is free to elide its creation entirely.



Related Topics



Leave a reply



Submit